mirror of
https://github.com/joomla/joomla-cms.git
synced 2024-06-25 23:02:55 +00:00
[add] Add support for PDO based connections for MySQL. Closes #4123
This commit is contained in:
parent
8c2b02640b
commit
216b687439
|
@ -193,7 +193,7 @@
|
|||
type="databaseconnection"
|
||||
label="COM_CONFIG_FIELD_DATABASE_TYPE_LABEL"
|
||||
description="COM_CONFIG_FIELD_DATABASE_TYPE_DESC"
|
||||
supported="mysql,mysqli,postgresql,sqlsrv,sqlazure"
|
||||
supported="mysql,mysqli,pdomysql,postgresql,sqlsrv,sqlazure"
|
||||
filter="string" />
|
||||
|
||||
<field
|
||||
|
|
|
@ -60,10 +60,11 @@ class ContactTableContact extends JTable
|
|||
$date = JFactory::getDate();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
$this->modified = $date->toSql();
|
||||
|
||||
if ($this->id)
|
||||
{
|
||||
// Existing item
|
||||
$this->modified = $date->toSql();
|
||||
$this->modified_by = $user->get('id');
|
||||
}
|
||||
else
|
||||
|
|
|
@ -103,7 +103,7 @@ abstract class FinderIndexer
|
|||
// Setup the adapter for the indexer.
|
||||
$format = JFactory::getDbo()->name;
|
||||
|
||||
if ($format == 'mysqli')
|
||||
if ($format == 'mysqli' || $format == 'pdomysql')
|
||||
{
|
||||
$format = 'mysql';
|
||||
}
|
||||
|
|
|
@ -198,10 +198,11 @@ class FinderTableFilter extends JTable
|
|||
$date = JFactory::getDate();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
$this->modified = $date->toSql();
|
||||
|
||||
if ($this->filter_id)
|
||||
{
|
||||
// Existing item
|
||||
$this->modified = $date->toSql();
|
||||
$this->modified_by = $user->get('id');
|
||||
}
|
||||
else
|
||||
|
|
|
@ -110,10 +110,12 @@ class NewsfeedsTableNewsfeed extends JTable
|
|||
{
|
||||
$date = JFactory::getDate();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
$this->modified = $date->toSql();
|
||||
|
||||
if ($this->id)
|
||||
{
|
||||
// Existing item
|
||||
$this->modified = $date->toSql();
|
||||
$this->modified_by = $user->get('id');
|
||||
}
|
||||
else
|
||||
|
|
|
@ -96,12 +96,9 @@ class RedirectTableLink extends JTable
|
|||
{
|
||||
$date = JFactory::getDate()->toSql();
|
||||
|
||||
if ($this->id)
|
||||
{
|
||||
// Existing item
|
||||
$this->modified_date = $date;
|
||||
}
|
||||
else
|
||||
$this->modified_date = $date;
|
||||
|
||||
if (!$this->id)
|
||||
{
|
||||
// New record.
|
||||
$this->created_date = $date;
|
||||
|
|
|
@ -156,9 +156,11 @@ class TagsTableTag extends JTableNested
|
|||
{
|
||||
$date = JFactory::getDate();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
$this->modified_time = $date->toSql();
|
||||
|
||||
if ($this->id) {
|
||||
// Existing item
|
||||
$this->modified_time = $date->toSql();
|
||||
$this->modified_user_id = $user->get('id');
|
||||
}
|
||||
else
|
||||
|
|
|
@ -46,6 +46,8 @@ class UsersTableNote extends JTable
|
|||
$date = JFactory::getDate()->toSql();
|
||||
$userId = JFactory::getUser()->get('id');
|
||||
|
||||
$this->modified_time = $date;
|
||||
|
||||
if (empty($this->id))
|
||||
{
|
||||
// New record.
|
||||
|
@ -55,7 +57,6 @@ class UsersTableNote extends JTable
|
|||
else
|
||||
{
|
||||
// Existing record.
|
||||
$this->modified_time = $date;
|
||||
$this->modified_user_id = $userId;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,10 +80,11 @@ class WeblinksTableWeblink extends JTable
|
|||
$date = JFactory::getDate();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
$this->modified = $date->toSql();
|
||||
|
||||
if ($this->id)
|
||||
{
|
||||
// Existing item
|
||||
$this->modified = $date->toSql();
|
||||
$this->modified_by = $user->get('id');
|
||||
}
|
||||
else
|
||||
|
|
|
@ -950,6 +950,7 @@ PHPMAILER_TLS="Could not start TLS"
|
|||
MYSQL="MySQL"
|
||||
MYSQLI="MySQLi"
|
||||
ORACLE="Oracle"
|
||||
PDOMYSQL="MySQL (PDO)"
|
||||
POSTGRESQL="PostgreSQL"
|
||||
SQLAZURE="Microsoft SQL Azure"
|
||||
SQLITE="SQLite"
|
||||
|
|
|
@ -180,6 +180,7 @@ INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="English (AU)"
|
|||
|
||||
;Database Model
|
||||
INSTL_DATABASE_COULD_NOT_CONNECT="Could not connect to the database. Connector returned number: %s"
|
||||
INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="The installer could not connect to the specified database and was unable to create the database. Please verify your settings and if necessary manually create your database."
|
||||
INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="Could not refresh manifest cache for extension: %s"
|
||||
INSTL_DATABASE_EMPTY_NAME=""
|
||||
INSTL_DATABASE_ERROR_BACKINGUP="Some errors occurred in backing up the database."
|
||||
|
@ -191,6 +192,8 @@ INSTL_DATABASE_FIX_TOO_LONG="The MySQL table prefix must be a maximum of 15 char
|
|||
INSTL_DATABASE_INVALID_DB_DETAILS="The database details provided are incorrect and/or empty."
|
||||
INSTL_DATABASE_INVALID_MYSQL_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_MYSQLI_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_PDOMYSQL_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_POSTGRESQL_VERSION="You need PostgreSQL 8.3.18 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_SQLSRV_VERSION="You need SQL Server 2008 R2 (10.50.1600.1) or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_SQLZURE_VERSION="You need SQL Server 2008 R2 (10.50.1600.1) or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_TYPE="Please select the database type"
|
||||
|
@ -306,6 +309,7 @@ SITE_NAME="Site Name"
|
|||
MYSQL="MySQL"
|
||||
MYSQLI="MySQLi"
|
||||
ORACLE="Oracle"
|
||||
PDOMYSQL="MySQL (PDO)"
|
||||
POSTGRESQL="PostgreSQL"
|
||||
SQLAZURE="Microsoft SQL Azure"
|
||||
SQLITE="SQLite"
|
||||
|
|
|
@ -180,6 +180,7 @@ INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="English (UK)"
|
|||
|
||||
;Database Model
|
||||
INSTL_DATABASE_COULD_NOT_CONNECT="Could not connect to the database. Connector returned number: %s"
|
||||
INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="The installer could not connect to the specified database and was unable to create the database. Please verify your settings and if necessary manually create your database."
|
||||
INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="Could not refresh manifest cache for extension: %s"
|
||||
INSTL_DATABASE_EMPTY_NAME=""
|
||||
INSTL_DATABASE_ERROR_BACKINGUP="Some errors occurred in backing up the database."
|
||||
|
@ -191,6 +192,8 @@ INSTL_DATABASE_FIX_TOO_LONG="The MySQL table prefix must be a maximum of 15 char
|
|||
INSTL_DATABASE_INVALID_DB_DETAILS="The database details provided are incorrect and/or empty."
|
||||
INSTL_DATABASE_INVALID_MYSQL_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_MYSQLI_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_PDOMYSQL_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_POSTGRESQL_VERSION="You need PostgreSQL 8.3.18 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_SQLSRV_VERSION="You need SQL Server 2008 R2 (10.50.1600.1) or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_SQLZURE_VERSION="You need SQL Server 2008 R2 (10.50.1600.1) or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_TYPE="Please select the database type"
|
||||
|
@ -306,6 +309,7 @@ SITE_NAME="Site Name"
|
|||
MYSQL="MySQL"
|
||||
MYSQLI="MySQLi"
|
||||
ORACLE="Oracle"
|
||||
PDOMYSQL="MySQL (PDO)"
|
||||
POSTGRESQL="PostgreSQL"
|
||||
SQLAZURE="Microsoft SQL Azure"
|
||||
SQLITE="SQLite"
|
||||
|
|
|
@ -178,6 +178,7 @@ INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="English (UK)"
|
|||
|
||||
;Database Model
|
||||
INSTL_DATABASE_COULD_NOT_CONNECT="Could not connect to the database. Connector returned number: %s"
|
||||
INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="The installer could not connect to the specified database and was unable to create the database. Please verify your settings and if necessary manually create your database."
|
||||
INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="Could not refresh manifest cache for extension: %s"
|
||||
INSTL_DATABASE_EMPTY_NAME=""
|
||||
INSTL_DATABASE_ERROR_BACKINGUP="Some errors occurred in backing up the database."
|
||||
|
@ -189,6 +190,8 @@ INSTL_DATABASE_FIX_TOO_LONG="The MySQL table prefix must be a maximum of 15 char
|
|||
INSTL_DATABASE_INVALID_DB_DETAILS="The database details provided are incorrect and/or empty."
|
||||
INSTL_DATABASE_INVALID_MYSQL_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_MYSQLI_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_PDOMYSQL_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_POSTGRESQL_VERSION="You need PostgreSQL 8.3.18 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_SQLSRV_VERSION="You need SQL Server 2008 R2 (10.50.1600.1) or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_SQLZURE_VERSION="You need SQL Server 2008 R2 (10.50.1600.1) or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_TYPE="Please select the database type"
|
||||
|
@ -304,6 +307,7 @@ SITE_NAME="Site Name"
|
|||
MYSQL="MySQL"
|
||||
MYSQLI="MySQLi"
|
||||
ORACLE="Oracle"
|
||||
PDOMYSQL="MySQL (PDO)"
|
||||
POSTGRESQL="PostgreSQL"
|
||||
SQLAZURE="Microsoft SQL Azure"
|
||||
SQLITE="SQLite"
|
||||
|
|
|
@ -180,6 +180,7 @@ INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="English (US)"
|
|||
|
||||
;Database Model
|
||||
INSTL_DATABASE_COULD_NOT_CONNECT="Could not connect to the database. Connector returned number: %s"
|
||||
INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="The installer could not connect to the specified database and was unable to create the database. Please verify your settings and if necessary manually create your database."
|
||||
INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="Could not refresh manifest cache for extension: %s"
|
||||
INSTL_DATABASE_EMPTY_NAME=""
|
||||
INSTL_DATABASE_ERROR_BACKINGUP="Some errors occurred in backing up the database."
|
||||
|
@ -191,6 +192,8 @@ INSTL_DATABASE_FIX_TOO_LONG="The MySQL table prefix must be a maximum of 15 char
|
|||
INSTL_DATABASE_INVALID_DB_DETAILS="The database details provided are incorrect and/or empty."
|
||||
INSTL_DATABASE_INVALID_MYSQL_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_MYSQLI_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_PDOMYSQL_VERSION="You need MySQL 5.0.4 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_POSTGRESQL_VERSION="You need PostgreSQL 8.3.18 or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_SQLSRV_VERSION="You need SQL Server 2008 R2 (10.50.1600.1) or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_SQLZURE_VERSION="You need SQL Server 2008 R2 (10.50.1600.1) or higher to continue the installation. Your version is: %s"
|
||||
INSTL_DATABASE_INVALID_TYPE="Please select the database type"
|
||||
|
@ -306,6 +309,7 @@ SITE_NAME="Site Name"
|
|||
MYSQL="MySQL"
|
||||
MYSQLI="MySQLi"
|
||||
ORACLE="Oracle"
|
||||
PDOMYSQL="MySQL (PDO)"
|
||||
POSTGRESQL="PostgreSQL"
|
||||
SQLAZURE="Microsoft SQL Azure"
|
||||
SQLITE="SQLite"
|
||||
|
|
|
@ -83,7 +83,7 @@ class InstallationModelDatabase extends JModelBase
|
|||
*
|
||||
* @param array $options The options to use for configuration
|
||||
*
|
||||
* @return boolean True on success
|
||||
* @return JDatabaseDriver|boolean Database object on success, boolean false on failure
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
|
@ -208,8 +208,70 @@ class InstallationModelDatabase extends JModelBase
|
|||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
$app->enqueueMessage(JText::sprintf('INSTL_DATABASE_COULD_NOT_CONNECT', $e->getMessage()), 'notice');
|
||||
return false;
|
||||
/*
|
||||
* We may get here if the database doesn't exist, if so then explain that to users instead of showing the database connector's error
|
||||
* This only supports PostgreSQL and the PDO MySQL drivers presently
|
||||
*
|
||||
* Error Messages:
|
||||
* PDO MySQL: [1049] Unknown database 'database_name'
|
||||
* PostgreSQL: Error connecting to PGSQL database
|
||||
*/
|
||||
if ($type == 'pdomysql' && strpos($e->getMessage(), '[1049] Unknown database') === 42)
|
||||
{
|
||||
/*
|
||||
* Now we're really getting insane here; we're going to try building a new JDatabaseDriver instance without the database name
|
||||
* in order to trick the connection into creating the database
|
||||
*/
|
||||
$altDBoptions = array(
|
||||
'driver' => $options->db_type,
|
||||
'host' => $options->db_host,
|
||||
'user' => $options->db_user,
|
||||
'password' => $options->db_pass,
|
||||
'prefix' => $options->db_prefix,
|
||||
'select' => $options->db_select
|
||||
);
|
||||
|
||||
$altDB = JDatabaseDriver::getInstance($altDBoptions);
|
||||
|
||||
// Try to create the database now using the alternate driver
|
||||
try
|
||||
{
|
||||
$this->createDB($altDB, $options, $altDB->hasUTFSupport());
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
// We did everything we could
|
||||
$app->enqueueMessage(JText::_('INSTL_DATABASE_COULD_NOT_CREATE_DATABASE'), 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we got here, the database should have been successfully created, now try one more time to get the version
|
||||
try
|
||||
{
|
||||
$db_version = $db->getVersion();
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
// We did everything we could
|
||||
$app->enqueueMessage(JText::sprintf('INSTL_DATABASE_COULD_NOT_CONNECT', $e->getMessage()), 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elseif ($type == 'postgresql' && strpos($e->getMessage(), 'Error connecting to PGSQL database') === 42)
|
||||
{
|
||||
$app->enqueueMessage(JText::_('INSTL_DATABASE_COULD_NOT_CREATE_DATABASE'), 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
// Anything getting into this part of the conditional either doesn't support manually creating the database or isn't that type of error
|
||||
else
|
||||
{
|
||||
$app->enqueueMessage(JText::sprintf('INSTL_DATABASE_COULD_NOT_CONNECT', $e->getMessage()), 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$db->isMinimumVersion())
|
||||
|
@ -218,7 +280,7 @@ class InstallationModelDatabase extends JModelBase
|
|||
return false;
|
||||
}
|
||||
|
||||
if (($type == 'mysql') || ($type == 'mysqli'))
|
||||
if (($type == 'mysql') || ($type == 'mysqli') || ($type == 'pdomysql'))
|
||||
{
|
||||
// @internal MySQL versions pre 5.1.6 forbid . / or \ or NULL
|
||||
if ((preg_match('#[\\\/\.\0]#', $options->db_name)) && (!version_compare($db_version, '5.1.6', '>=')))
|
||||
|
@ -377,7 +439,7 @@ class InstallationModelDatabase extends JModelBase
|
|||
$this->setDatabaseCharset($db, $options->db_name);
|
||||
|
||||
// Set the appropriate schema script based on UTF-8 support.
|
||||
if ($type == 'mysqli' || $type == 'mysql')
|
||||
if (($type == 'mysql') || ($type == 'mysqli') || ($type == 'pdomysql'))
|
||||
{
|
||||
$schema = 'sql/mysql/joomla.sql';
|
||||
}
|
||||
|
@ -406,7 +468,7 @@ class InstallationModelDatabase extends JModelBase
|
|||
// Attempt to update the table #__schema.
|
||||
$pathPart = JPATH_ADMINISTRATOR . '/components/com_admin/sql/updates/';
|
||||
|
||||
if ($type == 'mysqli' || $type == 'mysql')
|
||||
if (($type == 'mysql') || ($type == 'mysqli') || ($type == 'pdomysql'))
|
||||
{
|
||||
$pathPart .= 'mysql/';
|
||||
}
|
||||
|
@ -486,7 +548,7 @@ class InstallationModelDatabase extends JModelBase
|
|||
}
|
||||
|
||||
// Load the localise.sql for translating the data in joomla.sql
|
||||
if ($type == 'mysqli' || $type == 'mysql')
|
||||
if (($type == 'mysql') || ($type == 'mysqli') || ($type == 'pdomysql'))
|
||||
{
|
||||
$dblocalise = 'sql/mysql/localise.sql';
|
||||
}
|
||||
|
@ -583,7 +645,7 @@ class InstallationModelDatabase extends JModelBase
|
|||
// Build the path to the sample data file.
|
||||
$type = $options->db_type;
|
||||
|
||||
if ($type == 'mysqli')
|
||||
if ($type == 'mysqli' || $type == 'pdomysql')
|
||||
{
|
||||
$type = 'mysql';
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ class JFormFieldSample extends JFormFieldRadio
|
|||
$type = $this->form->getValue('db_type');
|
||||
|
||||
// Some database drivers share DDLs; point these drivers to the correct parent
|
||||
if ($type == 'mysqli')
|
||||
if ($type == 'mysqli' || $type == 'pdomysql')
|
||||
{
|
||||
$type = 'mysql';
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<field name="db_type" type="databaseconnection"
|
||||
id="db_type" class="inputbox"
|
||||
label="INSTL_DATABASE_TYPE_LABEL"
|
||||
supported="mysql,mysqli,postgresql,sqlsrv,sqlazure"
|
||||
supported="mysql,mysqli,pdomysql,postgresql,sqlsrv,sqlazure"
|
||||
required="true"
|
||||
default="mysqli"
|
||||
filter="string"
|
||||
|
|
|
@ -332,6 +332,7 @@ PHPMAILER_TLS="Could not start TLS"
|
|||
MYSQL="MySQL"
|
||||
MYSQLI="MySQLi"
|
||||
ORACLE="Oracle"
|
||||
PDOMYSQL="MySQL (PDO)"
|
||||
POSTGRESQL="PostgreSQL"
|
||||
SQLAZURE="Microsoft SQL Azure"
|
||||
SQLITE="SQLite"
|
||||
|
|
|
@ -891,7 +891,7 @@ class JInstaller extends JAdapter
|
|||
$db = & $this->_db;
|
||||
$dbDriver = strtolower($db->name);
|
||||
|
||||
if ($dbDriver == 'mysqli')
|
||||
if ($dbDriver == 'mysqli' || $dbDriver == 'pdomysql')
|
||||
{
|
||||
$dbDriver = 'mysql';
|
||||
}
|
||||
|
@ -902,7 +902,7 @@ class JInstaller extends JAdapter
|
|||
$fCharset = (strtolower($file->attributes()->charset) == 'utf8') ? 'utf8' : '';
|
||||
$fDriver = strtolower($file->attributes()->driver);
|
||||
|
||||
if ($fDriver == 'mysqli')
|
||||
if ($fDriver == 'mysqli' || $fDriver == 'pdomysql')
|
||||
{
|
||||
$fDriver = 'mysql';
|
||||
}
|
||||
|
@ -987,7 +987,7 @@ class JInstaller extends JAdapter
|
|||
{
|
||||
$dbDriver = strtolower($db->name);
|
||||
|
||||
if ($dbDriver == 'mysqli')
|
||||
if ($dbDriver == 'mysqli' || $dbDriver == 'pdomysql')
|
||||
{
|
||||
$dbDriver = 'mysql';
|
||||
}
|
||||
|
@ -1054,7 +1054,7 @@ class JInstaller extends JAdapter
|
|||
{
|
||||
$dbDriver = strtolower($db->name);
|
||||
|
||||
if ($dbDriver == 'mysqli')
|
||||
if ($dbDriver == 'mysqli' || $dbDriver == 'pdomysql')
|
||||
{
|
||||
$dbDriver = 'mysql';
|
||||
}
|
||||
|
@ -1068,7 +1068,7 @@ class JInstaller extends JAdapter
|
|||
// Assuming that the type is a mandatory attribute but if it is not mandatory then there should be a discussion for it.
|
||||
$uDriver = strtolower($attrs['type']);
|
||||
|
||||
if ($uDriver == 'mysqli')
|
||||
if ($uDriver == 'mysqli' || $uDriver == 'pdomysql')
|
||||
{
|
||||
$uDriver = 'mysql';
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ abstract class JSchemaChangeitem
|
|||
// Get the class name
|
||||
$dbname = $db->name;
|
||||
|
||||
if ($dbname == 'mysqli')
|
||||
if ($dbname == 'mysqli' || $dbname == 'pdomysql')
|
||||
{
|
||||
$dbname = 'mysql';
|
||||
}
|
||||
|
|
|
@ -195,7 +195,7 @@ class JSchemaChangeset
|
|||
// Get the folder from the database name
|
||||
$sqlFolder = $this->db->name;
|
||||
|
||||
if ($sqlFolder == 'mysqli')
|
||||
if ($sqlFolder == 'mysqli' || $sqlFolder == 'pdomysql')
|
||||
{
|
||||
$sqlFolder = 'mysql';
|
||||
}
|
||||
|
|
|
@ -201,13 +201,15 @@ abstract class JDatabaseDriverPdo extends JDatabaseDriver
|
|||
|
||||
break;
|
||||
|
||||
// The pdomysql case is a special case within the CMS environment
|
||||
case 'pdomysql':
|
||||
case 'mysql':
|
||||
$this->options['port'] = (isset($this->options['port'])) ? $this->options['port'] : 3306;
|
||||
|
||||
$format = 'mysql:host=#HOST#;port=#PORT#;dbname=#DBNAME#';
|
||||
$format = 'mysql:host=#HOST#;port=#PORT#;dbname=#DBNAME#;charset=#CHARSET#';
|
||||
|
||||
$replace = array('#HOST#', '#PORT#', '#DBNAME#');
|
||||
$with = array($this->options['host'], $this->options['port'], $this->options['database']);
|
||||
$replace = array('#HOST#', '#PORT#', '#DBNAME#', '#CHARSET#');
|
||||
$with = array($this->options['host'], $this->options['port'], $this->options['database'], $this->options['charset']);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -253,7 +255,6 @@ abstract class JDatabaseDriverPdo extends JDatabaseDriver
|
|||
break;
|
||||
|
||||
case 'sqlite':
|
||||
|
||||
if (isset($this->options['version']) && $this->options['version'] == 2)
|
||||
{
|
||||
$format = 'sqlite2:#DBNAME#';
|
||||
|
|
485
libraries/joomla/database/driver/pdomysql.php
Normal file
485
libraries/joomla/database/driver/pdomysql.php
Normal file
|
@ -0,0 +1,485 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* MySQL database driver supporting PDO based connections
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
* @see http://php.net/manual/en/ref.pdo-mysql.php
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseDriverPdomysql extends JDatabaseDriverPdo
|
||||
{
|
||||
/**
|
||||
* The name of the database driver.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.4
|
||||
*/
|
||||
public $name = 'pdomysql';
|
||||
|
||||
/**
|
||||
* The character(s) used to quote SQL statement names such as table names or field names,
|
||||
* etc. The child classes should define this as necessary. If a single character string the
|
||||
* same character is used for both sides of the quoted name, else the first character will be
|
||||
* used for the opening quote and the second for the closing quote.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.4
|
||||
*/
|
||||
protected $nameQuote = '`';
|
||||
|
||||
/**
|
||||
* The null or zero representation of a timestamp for the database driver. This should be
|
||||
* defined in child classes to hold the appropriate value for the engine.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.4
|
||||
*/
|
||||
protected $nullDate = '0000-00-00 00:00:00';
|
||||
|
||||
/**
|
||||
* The minimum supported database version.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.4
|
||||
*/
|
||||
protected static $dbMinimum = '5.0.4';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $options Array of database options with keys: host, user, password, database, select.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function __construct($options)
|
||||
{
|
||||
// Get some basic values from the options.
|
||||
$options['driver'] = 'mysql';
|
||||
$options['charset'] = (isset($options['charset'])) ? $options['charset'] : 'utf8';
|
||||
|
||||
$this->charset = $options['charset'];
|
||||
|
||||
// Finalize initialisation.
|
||||
parent::__construct($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the database if needed.
|
||||
*
|
||||
* @return void Returns void if the database connected successfully.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
parent::connect();
|
||||
|
||||
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the MySQL connector is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
return in_array('mysql', PDO::getAvailableDrivers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a table from the database.
|
||||
*
|
||||
* @param string $tableName The name of the database table to drop.
|
||||
* @param boolean $ifExists Optionally specify that the table must exist before it is dropped.
|
||||
*
|
||||
* @return JDatabaseDriverPdomysql Returns this object to support chaining.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function dropTable($tableName, $ifExists = true)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$query = $this->getQuery(true);
|
||||
|
||||
$query->setQuery('DROP TABLE ' . ($ifExists ? 'IF EXISTS ' : '') . $this->quoteName($tableName));
|
||||
|
||||
$this->setQuery($query);
|
||||
|
||||
$this->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a database for use.
|
||||
*
|
||||
* @param string $database The name of the database to select for use.
|
||||
*
|
||||
* @return boolean True if the database was successfully selected.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function select($database)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$this->setQuery('USE ' . $this->quoteName($database));
|
||||
|
||||
$this->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the database collation in use by sampling a text field of a table in the database.
|
||||
*
|
||||
* @return mixed The collation in use by the database (string) or boolean false if not supported.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getCollation()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Attempt to get the database collation by accessing the server system variable.
|
||||
$this->setQuery('SHOW VARIABLES LIKE "collation_database"');
|
||||
$result = $this->loadObject();
|
||||
|
||||
if (property_exists($result, 'Value'))
|
||||
{
|
||||
return $result->Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the table CREATE statement that creates the given tables.
|
||||
*
|
||||
* @param mixed $tables A table name or a list of table names.
|
||||
*
|
||||
* @return array A list of the create SQL for the tables.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getTableCreate($tables)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Initialise variables.
|
||||
$result = array();
|
||||
|
||||
// Sanitize input to an array and iterate over the list.
|
||||
settype($tables, 'array');
|
||||
|
||||
foreach ($tables as $table)
|
||||
{
|
||||
$this->setQuery('SHOW CREATE TABLE ' . $this->quoteName($table));
|
||||
|
||||
$row = $this->loadRow();
|
||||
|
||||
// Populate the result array based on the create statements.
|
||||
$result[$table] = $row[1];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves field information about a given table.
|
||||
*
|
||||
* @param string $table The name of the database table.
|
||||
* @param boolean $typeOnly True to only return field types.
|
||||
*
|
||||
* @return array An array of fields for the database table.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getTableColumns($table, $typeOnly = true)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
$result = array();
|
||||
|
||||
// Set the query to get the table fields statement.
|
||||
$this->setQuery('SHOW FULL COLUMNS FROM ' . $this->quoteName($table));
|
||||
|
||||
$fields = $this->loadObjectList();
|
||||
|
||||
// If we only want the type as the value add just that to the list.
|
||||
if ($typeOnly)
|
||||
{
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
$result[$field->Field] = preg_replace("/[(0-9)]/", '', $field->Type);
|
||||
}
|
||||
}
|
||||
// If we want the whole field data object add that to the list.
|
||||
else
|
||||
{
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
$result[$field->Field] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param string $table The name of the table.
|
||||
*
|
||||
* @return array An array of the column specification for the table.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getTableKeys($table)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Get the details columns information.
|
||||
$this->setQuery('SHOW KEYS FROM ' . $this->quoteName($table));
|
||||
|
||||
$keys = $this->loadObjectList();
|
||||
|
||||
return $keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of all tables in the database.
|
||||
*
|
||||
* @return array An array of all the tables in the database.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getTableList()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
// Set the query to get the tables statement.
|
||||
$this->setQuery('SHOW TABLES');
|
||||
$tables = $this->loadColumn();
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the database connector.
|
||||
*
|
||||
* @return string The database connector version.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
return $this->getOption(PDO::ATTR_SERVER_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks a table in the database.
|
||||
*
|
||||
* @param string $table The name of the table to unlock.
|
||||
*
|
||||
* @return JDatabaseDriverPdomysql Returns this object to support chaining.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function lockTable($table)
|
||||
{
|
||||
$this->setQuery('LOCK TABLES ' . $this->quoteName($table) . ' WRITE')->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames a table in the database.
|
||||
*
|
||||
* @param string $oldTable The name of the table to be renamed
|
||||
* @param string $newTable The new name for the table.
|
||||
* @param string $backup Not used by MySQL.
|
||||
* @param string $prefix Not used by MySQL.
|
||||
*
|
||||
* @return JDatabaseDriverPdomysql Returns this object to support chaining.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function renameTable($oldTable, $newTable, $backup = null, $prefix = null)
|
||||
{
|
||||
$this->setQuery('RENAME TABLE ' . $this->quoteName($oldTable) . ' TO ' . $this->quoteName($newTable));
|
||||
|
||||
$this->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to escape a string for usage in an SQL statement.
|
||||
*
|
||||
* Oracle escaping reference:
|
||||
* http://www.orafaq.com/wiki/SQL_FAQ#How_does_one_escape_special_characters_when_writing_SQL_queries.3F
|
||||
*
|
||||
* SQLite escaping notes:
|
||||
* http://www.sqlite.org/faq.html#q14
|
||||
*
|
||||
* Method body is as implemented by the Zend Framework
|
||||
*
|
||||
* Note: Using query objects with bound variables is
|
||||
* preferable to the below.
|
||||
*
|
||||
* @param string $text The string to be escaped.
|
||||
* @param boolean $extra Unused optional parameter to provide extra escaping.
|
||||
*
|
||||
* @return string The escaped string.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function escape($text, $extra = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (is_int($text) || is_float($text))
|
||||
{
|
||||
return $text;
|
||||
}
|
||||
|
||||
$result = substr($this->connection->quote($text), 1, -1);
|
||||
|
||||
if ($extra)
|
||||
{
|
||||
$result = addcslashes($result, '%_');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks tables in the database.
|
||||
*
|
||||
* @return JDatabaseDriverPdomysql Returns this object to support chaining.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function unlockTables()
|
||||
{
|
||||
$this->setQuery('UNLOCK TABLES')->execute();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to commit a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, commit to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function transactionCommit($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth <= 1)
|
||||
{
|
||||
parent::transactionCommit($toSavepoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to roll back a transaction.
|
||||
*
|
||||
* @param boolean $toSavepoint If true, rollback to the last savepoint.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function transactionRollback($toSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$toSavepoint || $this->transactionDepth <= 1)
|
||||
{
|
||||
parent::transactionRollback($toSavepoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
$savepoint = 'SP_' . ($this->transactionDepth - 1);
|
||||
$this->setQuery('ROLLBACK TO SAVEPOINT ' . $this->quoteName($savepoint));
|
||||
|
||||
if ($this->execute())
|
||||
{
|
||||
$this->transactionDepth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to initialize a transaction.
|
||||
*
|
||||
* @param boolean $asSavepoint If true and a transaction is already active, a savepoint will be created.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function transactionStart($asSavepoint = false)
|
||||
{
|
||||
$this->connect();
|
||||
|
||||
if (!$asSavepoint || !$this->transactionDepth)
|
||||
{
|
||||
parent::transactionStart($asSavepoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
$savepoint = 'SP_' . $this->transactionDepth;
|
||||
$this->setQuery('SAVEPOINT ' . $this->quoteName($savepoint));
|
||||
|
||||
if ($this->execute())
|
||||
{
|
||||
$this->transactionDepth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
113
libraries/joomla/database/exporter/pdomysql.php
Normal file
113
libraries/joomla/database/exporter/pdomysql.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* MySQL export driver for the PDO based MySQL database driver.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseExporterPdomysql extends JDatabaseExporter
|
||||
{
|
||||
/**
|
||||
* Builds the XML data for the tables to export.
|
||||
*
|
||||
* @return string An XML string
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXml()
|
||||
{
|
||||
$buffer = array();
|
||||
|
||||
$buffer[] = '<?xml version="1.0"?>';
|
||||
$buffer[] = '<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">';
|
||||
$buffer[] = ' <database name="">';
|
||||
|
||||
$buffer = array_merge($buffer, $this->buildXmlStructure());
|
||||
|
||||
$buffer[] = ' </database>';
|
||||
$buffer[] = '</mysqldump>';
|
||||
|
||||
return implode("\n", $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XML structure to export.
|
||||
*
|
||||
* @return array An array of XML lines (strings).
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws Exception if an error occurs.
|
||||
*/
|
||||
protected function buildXmlStructure()
|
||||
{
|
||||
$buffer = array();
|
||||
|
||||
foreach ($this->from as $table)
|
||||
{
|
||||
// Replace the magic prefix if found.
|
||||
$table = $this->getGenericTableName($table);
|
||||
|
||||
// Get the details columns information.
|
||||
$fields = $this->db->getTableColumns($table, false);
|
||||
$keys = $this->db->getTableKeys($table);
|
||||
|
||||
$buffer[] = ' <table_structure name="' . $table . '">';
|
||||
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
$buffer[] = ' <field Field="' . $field->Field . '"' . ' Type="' . $field->Type . '"' . ' Null="' . $field->Null . '"' . ' Key="' .
|
||||
$field->Key . '"' . (isset($field->Default) ? ' Default="' . $field->Default . '"' : '') . ' Extra="' . $field->Extra . '"' .
|
||||
' />';
|
||||
}
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
$buffer[] = ' <key Table="' . $table . '"' . ' Non_unique="' . $key->Non_unique . '"' . ' Key_name="' . $key->Key_name . '"' .
|
||||
' Seq_in_index="' . $key->Seq_in_index . '"' . ' Column_name="' . $key->Column_name . '"' . ' Collation="' . $key->Collation . '"' .
|
||||
' Null="' . $key->Null . '"' . ' Index_type="' . $key->Index_type . '"' . ' Comment="' . htmlspecialchars($key->Comment) . '"' .
|
||||
' />';
|
||||
}
|
||||
|
||||
$buffer[] = ' </table_structure>';
|
||||
}
|
||||
|
||||
return $buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return JDatabaseExporterPdomysql Method supports chaining.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws Exception if an error is encountered.
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// Check if the db connector has been set.
|
||||
if (!($this->db instanceof JDatabaseDriverPdomysql))
|
||||
{
|
||||
throw new Exception('JPLATFORM_ERROR_DATABASE_CONNECTOR_WRONG_TYPE');
|
||||
}
|
||||
|
||||
// Check if the tables have been specified.
|
||||
if (empty($this->from))
|
||||
{
|
||||
throw new Exception('JPLATFORM_ERROR_NO_TABLES_SPECIFIED');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
437
libraries/joomla/database/importer/pdomysql.php
Normal file
437
libraries/joomla/database/importer/pdomysql.php
Normal file
|
@ -0,0 +1,437 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* MySQL import driver for the PDO based MySQL database driver.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseImporterPdomysql extends JDatabaseImporter
|
||||
{
|
||||
/**
|
||||
* Get the SQL syntax to add a column.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param SimpleXMLElement $field The XML field definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getAddColumnSQL($table, SimpleXMLElement $field)
|
||||
{
|
||||
$sql = 'ALTER TABLE ' . $this->db->quoteName($table) . ' ADD COLUMN ' . $this->getColumnSQL($field);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to add a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param array $keys An array of the fields pertaining to this key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getAddKeySQL($table, $keys)
|
||||
{
|
||||
$sql = 'ALTER TABLE ' . $this->db->quoteName($table) . ' ADD ' . $this->getKeySQL($keys);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get alters for table if there is a difference.
|
||||
*
|
||||
* @param SimpleXMLElement $structure The XML structure pf the table.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getAlterTableSQL(SimpleXMLElement $structure)
|
||||
{
|
||||
// Initialise variables.
|
||||
$table = $this->getRealTableName($structure['name']);
|
||||
$oldFields = $this->db->getTableColumns($table);
|
||||
$oldKeys = $this->db->getTableKeys($table);
|
||||
$alters = array();
|
||||
|
||||
// Get the fields and keys from the XML that we are aiming for.
|
||||
$newFields = $structure->xpath('field');
|
||||
$newKeys = $structure->xpath('key');
|
||||
|
||||
// Loop through each field in the new structure.
|
||||
foreach ($newFields as $field)
|
||||
{
|
||||
$fName = (string) $field['Field'];
|
||||
|
||||
if (isset($oldFields[$fName]))
|
||||
{
|
||||
// The field exists, check it's the same.
|
||||
$column = $oldFields[$fName];
|
||||
|
||||
// Test whether there is a change.
|
||||
$change = ((string) $field['Type'] != $column->Type) || ((string) $field['Null'] != $column->Null)
|
||||
|| ((string) $field['Default'] != $column->Default) || ((string) $field['Extra'] != $column->Extra);
|
||||
|
||||
if ($change)
|
||||
{
|
||||
$alters[] = $this->getChangeColumnSQL($table, $field);
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldFields[$fName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The field is new.
|
||||
$alters[] = $this->getAddColumnSQL($table, $field);
|
||||
}
|
||||
}
|
||||
|
||||
// Any columns left are orphans
|
||||
foreach ($oldFields as $name => $column)
|
||||
{
|
||||
// Delete the column.
|
||||
$alters[] = $this->getDropColumnSQL($table, $name);
|
||||
}
|
||||
|
||||
// Get the lookups for the old and new keys.
|
||||
$oldLookup = $this->getKeyLookup($oldKeys);
|
||||
$newLookup = $this->getKeyLookup($newKeys);
|
||||
|
||||
// Loop through each key in the new structure.
|
||||
foreach ($newLookup as $name => $keys)
|
||||
{
|
||||
// Check if there are keys on this field in the existing table.
|
||||
if (isset($oldLookup[$name]))
|
||||
{
|
||||
$same = true;
|
||||
$newCount = count($newLookup[$name]);
|
||||
$oldCount = count($oldLookup[$name]);
|
||||
|
||||
// There is a key on this field in the old and new tables. Are they the same?
|
||||
if ($newCount == $oldCount)
|
||||
{
|
||||
// Need to loop through each key and do a fine grained check.
|
||||
for ($i = 0; $i < $newCount; $i++)
|
||||
{
|
||||
$same = (((string) $newLookup[$name][$i]['Non_unique'] == $oldLookup[$name][$i]->Non_unique)
|
||||
&& ((string) $newLookup[$name][$i]['Column_name'] == $oldLookup[$name][$i]->Column_name)
|
||||
&& ((string) $newLookup[$name][$i]['Seq_in_index'] == $oldLookup[$name][$i]->Seq_in_index)
|
||||
&& ((string) $newLookup[$name][$i]['Collation'] == $oldLookup[$name][$i]->Collation)
|
||||
&& ((string) $newLookup[$name][$i]['Index_type'] == $oldLookup[$name][$i]->Index_type));
|
||||
|
||||
/*
|
||||
Debug.
|
||||
echo '<pre>';
|
||||
echo '<br />Non_unique: '.
|
||||
((string) $newLookup[$name][$i]['Non_unique'] == $oldLookup[$name][$i]->Non_unique ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Non_unique'].' vs '.$oldLookup[$name][$i]->Non_unique;
|
||||
echo '<br />Column_name: '.
|
||||
((string) $newLookup[$name][$i]['Column_name'] == $oldLookup[$name][$i]->Column_name ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Column_name'].' vs '.$oldLookup[$name][$i]->Column_name;
|
||||
echo '<br />Seq_in_index: '.
|
||||
((string) $newLookup[$name][$i]['Seq_in_index'] == $oldLookup[$name][$i]->Seq_in_index ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Seq_in_index'].' vs '.$oldLookup[$name][$i]->Seq_in_index;
|
||||
echo '<br />Collation: '.
|
||||
((string) $newLookup[$name][$i]['Collation'] == $oldLookup[$name][$i]->Collation ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Collation'].' vs '.$oldLookup[$name][$i]->Collation;
|
||||
echo '<br />Index_type: '.
|
||||
((string) $newLookup[$name][$i]['Index_type'] == $oldLookup[$name][$i]->Index_type ? 'Pass' : 'Fail').' '.
|
||||
(string) $newLookup[$name][$i]['Index_type'].' vs '.$oldLookup[$name][$i]->Index_type;
|
||||
echo '<br />Same = '.($same ? 'true' : 'false');
|
||||
echo '</pre>';
|
||||
*/
|
||||
|
||||
if (!$same)
|
||||
{
|
||||
// Break out of the loop. No need to check further.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Count is different, just drop and add.
|
||||
$same = false;
|
||||
}
|
||||
|
||||
if (!$same)
|
||||
{
|
||||
$alters[] = $this->getDropKeySQL($table, $name);
|
||||
$alters[] = $this->getAddKeySQL($table, $keys);
|
||||
}
|
||||
|
||||
// Unset this field so that what we have left are fields that need to be removed.
|
||||
unset($oldLookup[$name]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a new key.
|
||||
$alters[] = $this->getAddKeySQL($table, $keys);
|
||||
}
|
||||
}
|
||||
|
||||
// Any keys left are orphans.
|
||||
foreach ($oldLookup as $name => $keys)
|
||||
{
|
||||
if (strtoupper($name) == 'PRIMARY')
|
||||
{
|
||||
$alters[] = $this->getDropPrimaryKeySQL($table);
|
||||
}
|
||||
else
|
||||
{
|
||||
$alters[] = $this->getDropKeySQL($table, $name);
|
||||
}
|
||||
}
|
||||
|
||||
return $alters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the syntax to alter a column.
|
||||
*
|
||||
* @param string $table The name of the database table to alter.
|
||||
* @param SimpleXMLElement $field The XML definition for the field.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getChangeColumnSQL($table, SimpleXMLElement $field)
|
||||
{
|
||||
$sql = 'ALTER TABLE ' . $this->db->quoteName($table) . ' CHANGE COLUMN ' . $this->db->quoteName((string) $field['Field']) . ' '
|
||||
. $this->getColumnSQL($field);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a single column that would be included in a table create or alter statement.
|
||||
*
|
||||
* @param SimpleXMLElement $field The XML field definition.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getColumnSQL(SimpleXMLElement $field)
|
||||
{
|
||||
// Initialise variables.
|
||||
// TODO Incorporate into parent class and use $this.
|
||||
$blobs = array('text', 'smalltext', 'mediumtext', 'largetext');
|
||||
|
||||
$fName = (string) $field['Field'];
|
||||
$fType = (string) $field['Type'];
|
||||
$fNull = (string) $field['Null'];
|
||||
$fDefault = isset($field['Default']) ? (string) $field['Default'] : null;
|
||||
$fExtra = (string) $field['Extra'];
|
||||
|
||||
$sql = $this->db->quoteName($fName) . ' ' . $fType;
|
||||
|
||||
if ($fNull == 'NO')
|
||||
{
|
||||
if (in_array($fType, $blobs) || $fDefault === null)
|
||||
{
|
||||
$sql .= ' NOT NULL';
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO Don't quote numeric values.
|
||||
$sql .= ' NOT NULL DEFAULT ' . $this->db->quote($fDefault);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($fDefault === null)
|
||||
{
|
||||
$sql .= ' DEFAULT NULL';
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO Don't quote numeric values.
|
||||
$sql .= ' DEFAULT ' . $this->db->quote($fDefault);
|
||||
}
|
||||
}
|
||||
|
||||
if ($fExtra)
|
||||
{
|
||||
$sql .= ' ' . strtoupper($fExtra);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a column.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param string $name The name of the field to drop.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getDropColumnSQL($table, $name)
|
||||
{
|
||||
$sql = 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP COLUMN ' . $this->db->quoteName($name);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
* @param string $name The name of the key to drop.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getDropKeySQL($table, $name)
|
||||
{
|
||||
$sql = 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP KEY ' . $this->db->quoteName($name);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax to drop a key.
|
||||
*
|
||||
* @param string $table The table name.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getDropPrimaryKeySQL($table)
|
||||
{
|
||||
$sql = 'ALTER TABLE ' . $this->db->quoteName($table) . ' DROP PRIMARY KEY';
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the details list of keys for a table.
|
||||
*
|
||||
* @param array $keys An array of objects that comprise the keys for the table.
|
||||
*
|
||||
* @return array The lookup array. array({key name} => array(object, ...))
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function getKeyLookup($keys)
|
||||
{
|
||||
// First pass, create a lookup of the keys.
|
||||
$lookup = array();
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if ($key instanceof SimpleXMLElement)
|
||||
{
|
||||
$kName = (string) $key['Key_name'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$kName = $key->Key_name;
|
||||
}
|
||||
|
||||
if (empty($lookup[$kName]))
|
||||
{
|
||||
$lookup[$kName] = array();
|
||||
}
|
||||
|
||||
$lookup[$kName][] = $key;
|
||||
}
|
||||
|
||||
return $lookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SQL syntax for a key.
|
||||
*
|
||||
* @param array $columns An array of SimpleXMLElement objects comprising the key.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getKeySQL($columns)
|
||||
{
|
||||
// TODO Error checking on array and element types.
|
||||
|
||||
$kNonUnique = (string) $columns[0]['Non_unique'];
|
||||
$kName = (string) $columns[0]['Key_name'];
|
||||
$kColumn = (string) $columns[0]['Column_name'];
|
||||
$prefix = '';
|
||||
|
||||
if ($kName == 'PRIMARY')
|
||||
{
|
||||
$prefix = 'PRIMARY ';
|
||||
}
|
||||
elseif ($kNonUnique == 0)
|
||||
{
|
||||
$prefix = 'UNIQUE ';
|
||||
}
|
||||
|
||||
$nColumns = count($columns);
|
||||
$kColumns = array();
|
||||
|
||||
if ($nColumns == 1)
|
||||
{
|
||||
$kColumns[] = $this->db->quoteName($kColumn);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($columns as $column)
|
||||
{
|
||||
$kColumns[] = (string) $column['Column_name'];
|
||||
}
|
||||
}
|
||||
|
||||
$sql = $prefix . 'KEY ' . ($kName != 'PRIMARY' ? $this->db->quoteName($kName) : '') . ' (' . implode(',', $kColumns) . ')';
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all data and options are in order prior to exporting.
|
||||
*
|
||||
* @return JDatabaseImporterPdomysql Method supports chaining.
|
||||
*
|
||||
* @since 3.4
|
||||
* @throws Exception if an error is encountered.
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
// Check if the db connector has been set.
|
||||
if (!($this->db instanceof JDatabaseDriverPdomysql))
|
||||
{
|
||||
throw new Exception('JPLATFORM_ERROR_DATABASE_CONNECTOR_WRONG_TYPE');
|
||||
}
|
||||
|
||||
// Check if the tables have been specified.
|
||||
if (empty($this->from))
|
||||
{
|
||||
throw new Exception('JPLATFORM_ERROR_NO_TABLES_SPECIFIED');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
22
libraries/joomla/database/iterator/pdomysql.php
Normal file
22
libraries/joomla/database/iterator/pdomysql.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* MySQL database iterator for the PDO based MySQL database driver.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
* @see http://dev.mysql.com/doc/
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseIteratorPdomysql extends JDatabaseIteratorPdo
|
||||
{
|
||||
}
|
21
libraries/joomla/database/query/pdomysql.php
Normal file
21
libraries/joomla/database/query/pdomysql.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Query Building Class.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Database
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseQueryPdomysql extends JDatabaseQueryMysqli
|
||||
{
|
||||
}
|
|
@ -210,10 +210,11 @@ class JTableCategory extends JTableNested
|
|||
$date = JFactory::getDate();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
$this->modified_time = $date->toSql();
|
||||
|
||||
if ($this->id)
|
||||
{
|
||||
// Existing category
|
||||
$this->modified_time = $date->toSql();
|
||||
$this->modified_user_id = $user->get('id');
|
||||
}
|
||||
else
|
||||
|
|
|
@ -249,10 +249,11 @@ class JTableContent extends JTable
|
|||
$date = JFactory::getDate();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
$this->modified = $date->toSql();
|
||||
|
||||
if ($this->id)
|
||||
{
|
||||
// Existing item
|
||||
$this->modified = $date->toSql();
|
||||
$this->modified_by = $user->get('id');
|
||||
}
|
||||
else
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<php>
|
||||
<const name="JTEST_DATABASE_MYSQL_DSN" value="host=localhost;dbname=joomla_ut;user=utuser;pass=ut1234" />
|
||||
<const name="JTEST_DATABASE_MYSQLI_DSN" value="host=localhost;dbname=joomla_ut;user=utuser;pass=ut1234" />
|
||||
<const name="JTEST_DATABASE_PDO_MYSQL_DSN" value="host=localhost;dbname=joomla_ut;user=utuser;pass=ut1234" />
|
||||
<const name="JTEST_DATABASE_POSTGRESQL_DSN" value="host=localhost;port=5432;dbname=joomla_ut;user=utuser;pass=ut1234" />
|
||||
<const name="JTEST_DATABASE_SQLSRV_DSN" value="host=localhost;dbname=joomla_ut;user=utuser;pass=ut1234" />
|
||||
</php>
|
||||
|
|
|
@ -749,7 +749,7 @@ class PlgSystemDebug extends JPlugin
|
|||
// Run a SHOW PROFILE query.
|
||||
$profile = '';
|
||||
|
||||
if (in_array($db->name, array('mysqli', 'mysql')))
|
||||
if (in_array($db->name, array('mysqli', 'mysql', 'pdomysql')))
|
||||
{
|
||||
if (isset($this->sqlShowProfileEach[$id]))
|
||||
{
|
||||
|
@ -1379,7 +1379,7 @@ class PlgSystemDebug extends JPlugin
|
|||
}
|
||||
}
|
||||
|
||||
if (in_array($db->name, array('mysqli', 'mysql', 'postgresql')))
|
||||
if (in_array($db->name, array('mysqli', 'mysql', 'pdomysql', 'postgresql')))
|
||||
{
|
||||
$log = $db->getLog();
|
||||
|
||||
|
|
138
tests/unit/core/case/database/pdomysql.php
Normal file
138
tests/unit/core/case/database/pdomysql.php
Normal file
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.Test
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract test case class for MySQL database testing with the PDO based driver.
|
||||
*
|
||||
* @package Joomla.Test
|
||||
* @since 3.4
|
||||
*/
|
||||
abstract class TestCaseDatabasePdomysql extends TestCaseDatabase
|
||||
{
|
||||
/**
|
||||
* @var JDatabaseDriverPdomysql The active database driver being used for the tests.
|
||||
* @since 3.4
|
||||
*/
|
||||
protected static $driver;
|
||||
|
||||
/**
|
||||
* @var array The JDatabaseDriver options for the connection.
|
||||
* @since 3.4
|
||||
*/
|
||||
private static $_options = array('driver' => 'pdomysql');
|
||||
|
||||
/**
|
||||
* @var JDatabaseDriverPdomysql The saved database driver to be restored after these tests.
|
||||
* @since 3.4
|
||||
*/
|
||||
private static $_stash;
|
||||
|
||||
/**
|
||||
* This method is called before the first test of this test class is run.
|
||||
*
|
||||
* An example DSN would be: host=localhost;dbname=joomla_ut;user=utuser;pass=ut1234
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public static function setUpBeforeClass()
|
||||
{
|
||||
// First let's look to see if we have a DSN defined or in the environment variables.
|
||||
if (defined('JTEST_DATABASE_PDO_MYSQL_DSN') || getenv('JTEST_DATABASE_PDO_MYSQL_DSN'))
|
||||
{
|
||||
$dsn = defined('JTEST_DATABASE_PDO_MYSQL_DSN') ? JTEST_DATABASE_PDO_MYSQL_DSN : getenv('JTEST_DATABASE_PDO_MYSQL_DSN');
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// First let's trim the mysql: part off the front of the DSN if it exists.
|
||||
if (strpos($dsn, 'mysql:') === 0)
|
||||
{
|
||||
$dsn = substr($dsn, 6);
|
||||
}
|
||||
|
||||
// Split the DSN into its parts over semicolons.
|
||||
$parts = explode(';', $dsn);
|
||||
|
||||
// Parse each part and populate the options array.
|
||||
foreach ($parts as $part)
|
||||
{
|
||||
list ($k, $v) = explode('=', $part, 2);
|
||||
|
||||
switch ($k)
|
||||
{
|
||||
case 'host':
|
||||
self::$_options['host'] = $v;
|
||||
break;
|
||||
case 'dbname':
|
||||
self::$_options['database'] = $v;
|
||||
break;
|
||||
case 'user':
|
||||
self::$_options['user'] = $v;
|
||||
break;
|
||||
case 'pass':
|
||||
self::$_options['password'] = $v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Attempt to instantiate the driver.
|
||||
self::$driver = JDatabaseDriver::getInstance(self::$_options);
|
||||
}
|
||||
catch (RuntimeException $e)
|
||||
{
|
||||
self::$driver = null;
|
||||
}
|
||||
|
||||
// If for some reason an exception object was returned set our database object to null.
|
||||
if (self::$driver instanceof Exception)
|
||||
{
|
||||
self::$driver = null;
|
||||
}
|
||||
|
||||
// Setup the factory pointer for the driver and stash the old one.
|
||||
self::$_stash = JFactory::$database;
|
||||
JFactory::$database = self::$driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called after the last test of this test class is run.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public static function tearDownAfterClass()
|
||||
{
|
||||
JFactory::$database = self::$_stash;
|
||||
self::$driver = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default database connection for running the tests.
|
||||
*
|
||||
* @return PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
protected function getConnection()
|
||||
{
|
||||
// Compile the connection DSN.
|
||||
$dsn = 'mysql:host=' . self::$_options['host'] . ';dbname=' . self::$_options['database'];
|
||||
|
||||
// Create the PDO object from the DSN and options.
|
||||
$pdo = new PDO($dsn, self::$_options['user'], self::$_options['password']);
|
||||
|
||||
return $this->createDefaultDBConnection($pdo, self::$_options['database']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,820 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.UnitTest
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test class for JDatabaseDriverPdomysql.
|
||||
*
|
||||
* @package Joomla.UnitTest
|
||||
* @subpackage Database
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseDriverPdomysqlTest extends TestCaseDatabasePdomysql
|
||||
{
|
||||
/**
|
||||
* Data for the testEscape test.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function dataTestEscape()
|
||||
{
|
||||
return array(
|
||||
array("'%_abc123", false, '\\\'%_abc123'),
|
||||
array("'%_abc123", true, '\\\'\\%\_abc123')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for the testTransactionRollback test.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function dataTestTransactionRollback()
|
||||
{
|
||||
return array(array(null, 0), array('transactionSavepoint', 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the __destruct method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function test__destruct()
|
||||
{
|
||||
$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the connected method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testConnected()
|
||||
{
|
||||
$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the dropTable method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testDropTable()
|
||||
{
|
||||
// Create #__bar table first
|
||||
self::$driver->setQuery('CREATE TABLE IF NOT EXISTS `#__bar` (`id` int(10) unsigned NOT NULL);');
|
||||
self::$driver->execute();
|
||||
|
||||
// Check return self or not.
|
||||
$this->assertThat(
|
||||
self::$driver->dropTable('#__bar', true),
|
||||
$this->isInstanceOf('JDatabaseDriverPdomysql'),
|
||||
'The table is dropped if present.'
|
||||
);
|
||||
|
||||
// Check is table dropped.
|
||||
self::$driver->setQuery("SHOW TABLES LIKE '%#__bar%'");
|
||||
$exists = self::$driver->loadResult();
|
||||
|
||||
$this->assertNull($exists);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the escape method.
|
||||
*
|
||||
* @param string $text The string to be escaped.
|
||||
* @param boolean $extra Optional parameter to provide extra escaping.
|
||||
* @param string $expected The expected result.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider dataTestEscape
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testEscape($text, $extra, $expected)
|
||||
{
|
||||
$this->assertThat(
|
||||
self::$driver->escape($text, $extra),
|
||||
$this->equalTo($expected),
|
||||
'The string was not escaped properly'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getAffectedRows method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetAffectedRows()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->delete();
|
||||
$query->from('#__dbtest');
|
||||
self::$driver->setQuery($query);
|
||||
|
||||
self::$driver->execute();
|
||||
|
||||
$this->assertThat(
|
||||
self::$driver->getAffectedRows(),
|
||||
$this->equalTo(4),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getCollation method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetCollation()
|
||||
{
|
||||
$this->assertThat(
|
||||
self::$driver->getCollation(),
|
||||
$this->equalTo('utf8_general_ci'),
|
||||
'Line:' . __LINE__ . ' The getCollation method should return the collation of the database.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getExporter method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetExporter()
|
||||
{
|
||||
$this->assertThat(
|
||||
self::$driver->getExporter(),
|
||||
$this->isInstanceOf('JDatabaseExporterPdomysql'),
|
||||
'Line:' . __LINE__ . ' The getExporter method should return the correct exporter.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getImporter method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetImporter()
|
||||
{
|
||||
$this->assertThat(
|
||||
self::$driver->getImporter(),
|
||||
$this->isInstanceOf('JDatabaseImporterPdomysql'),
|
||||
'Line:' . __LINE__ . ' The getImporter method should return the correct importer.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getNumRows method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetNumRows()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('*');
|
||||
$query->from('#__dbtest');
|
||||
$query->where('description = ' . self::$driver->quote('one'));
|
||||
self::$driver->setQuery($query);
|
||||
|
||||
$res = self::$driver->execute();
|
||||
|
||||
$this->assertThat(
|
||||
self::$driver->getNumRows($res),
|
||||
$this->equalTo(2),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getTableCreate method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetTableCreate()
|
||||
{
|
||||
$this->assertThat(
|
||||
self::$driver->getTableCreate('#__dbtest'),
|
||||
$this->isType('array'),
|
||||
'The statement to create the table is returned in an array.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getTableColumns method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetTableColumns()
|
||||
{
|
||||
$tableCol = array('id' => 'int unsigned', 'title' => 'varchar', 'start_date' => 'datetime', 'description' => 'text');
|
||||
|
||||
$this->assertThat(
|
||||
self::$driver->getTableColumns('#__dbtest'),
|
||||
$this->equalTo($tableCol),
|
||||
__LINE__
|
||||
);
|
||||
|
||||
/* Not only type field */
|
||||
$id = new stdClass;
|
||||
$id->Default = null;
|
||||
$id->Field = 'id';
|
||||
$id->Type = 'int(10) unsigned';
|
||||
$id->Null = 'NO';
|
||||
$id->Key = 'PRI';
|
||||
$id->Collation = null;
|
||||
$id->Extra = 'auto_increment';
|
||||
$id->Privileges = 'select,insert,update,references';
|
||||
$id->Comment = '';
|
||||
|
||||
$title = new stdClass;
|
||||
$title->Default = null;
|
||||
$title->Field = 'title';
|
||||
$title->Type = 'varchar(50)';
|
||||
$title->Null = 'NO';
|
||||
$title->Key = '';
|
||||
$title->Collation = 'utf8_general_ci';
|
||||
$title->Extra = '';
|
||||
$title->Privileges = 'select,insert,update,references';
|
||||
$title->Comment = '';
|
||||
|
||||
$start_date = new stdClass;
|
||||
$start_date->Default = null;
|
||||
$start_date->Field = 'start_date';
|
||||
$start_date->Type = 'datetime';
|
||||
$start_date->Null = 'NO';
|
||||
$start_date->Key = '';
|
||||
$start_date->Collation = null;
|
||||
$start_date->Extra = '';
|
||||
$start_date->Privileges = 'select,insert,update,references';
|
||||
$start_date->Comment = '';
|
||||
|
||||
$description = new stdClass;
|
||||
$description->Default = null;
|
||||
$description->Field = 'description';
|
||||
$description->Type = 'text';
|
||||
$description->Null = 'NO';
|
||||
$description->Key = '';
|
||||
$description->Collation = 'utf8_general_ci';
|
||||
$description->Extra = '';
|
||||
$description->Privileges = 'select,insert,update,references';
|
||||
$description->Comment = '';
|
||||
|
||||
$this->assertThat(
|
||||
self::$driver->getTableColumns('#__dbtest', false),
|
||||
$this->equalTo(
|
||||
array(
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'start_date' => $start_date,
|
||||
'description' => $description
|
||||
)
|
||||
),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getTableKeys method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetTableKeys()
|
||||
{
|
||||
$this->assertThat(
|
||||
self::$driver->getTableKeys('#__dbtest'),
|
||||
$this->isType('array'),
|
||||
'The list of keys for the table is returned in an array.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getTableList method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetTableList()
|
||||
{
|
||||
$this->assertThat(
|
||||
self::$driver->getTableList(),
|
||||
$this->isType('array'),
|
||||
'The list of tables for the database is returned in an array.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getVersion method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetVersion()
|
||||
{
|
||||
$this->assertThat(
|
||||
strlen(self::$driver->getVersion()),
|
||||
$this->greaterThan(0),
|
||||
'Line:' . __LINE__ . ' The getVersion method should return something without error.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test insertid method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testInsertid()
|
||||
{
|
||||
$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadAssoc method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadAssoc()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('title');
|
||||
$query->from('#__dbtest');
|
||||
self::$driver->setQuery($query);
|
||||
$result = self::$driver->loadAssoc();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo(
|
||||
array(
|
||||
'title' => 'Testing'
|
||||
)),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadAssocList method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadAssocList()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('title');
|
||||
$query->from('#__dbtest');
|
||||
self::$driver->setQuery($query);
|
||||
$result = self::$driver->loadAssocList();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo(array(array('title' => 'Testing'), array('title' => 'Testing2'), array('title' => 'Testing3'), array('title' => 'Testing4'))),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadColumn method
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadColumn()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('title');
|
||||
$query->from('#__dbtest');
|
||||
self::$driver->setQuery($query);
|
||||
$result = self::$driver->loadColumn();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo(array('Testing', 'Testing2', 'Testing3', 'Testing4')),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadNextObject method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadNextObject()
|
||||
{
|
||||
$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadNextRow method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadNextRow()
|
||||
{
|
||||
$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadObject method
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadObject()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('*');
|
||||
$query->from('#__dbtest');
|
||||
$query->where('description=' . self::$driver->quote('three'));
|
||||
self::$driver->setQuery($query);
|
||||
$result = self::$driver->loadObject();
|
||||
|
||||
$objCompare = new stdClass;
|
||||
$objCompare->id = 3;
|
||||
$objCompare->title = 'Testing3';
|
||||
$objCompare->start_date = '1980-04-18 00:00:00';
|
||||
$objCompare->description = 'three';
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo($objCompare),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadObjectList method
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadObjectList()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('*');
|
||||
$query->from('#__dbtest');
|
||||
$query->order('id');
|
||||
self::$driver->setQuery($query);
|
||||
$result = self::$driver->loadObjectList();
|
||||
|
||||
$expected = array();
|
||||
|
||||
$objCompare = new stdClass;
|
||||
$objCompare->id = 1;
|
||||
$objCompare->title = 'Testing';
|
||||
$objCompare->start_date = '1980-04-18 00:00:00';
|
||||
$objCompare->description = 'one';
|
||||
|
||||
$expected[] = clone $objCompare;
|
||||
|
||||
$objCompare = new stdClass;
|
||||
$objCompare->id = 2;
|
||||
$objCompare->title = 'Testing2';
|
||||
$objCompare->start_date = '1980-04-18 00:00:00';
|
||||
$objCompare->description = 'one';
|
||||
|
||||
$expected[] = clone $objCompare;
|
||||
|
||||
$objCompare = new stdClass;
|
||||
$objCompare->id = 3;
|
||||
$objCompare->title = 'Testing3';
|
||||
$objCompare->start_date = '1980-04-18 00:00:00';
|
||||
$objCompare->description = 'three';
|
||||
|
||||
$expected[] = clone $objCompare;
|
||||
|
||||
$objCompare = new stdClass;
|
||||
$objCompare->id = 4;
|
||||
$objCompare->title = 'Testing4';
|
||||
$objCompare->start_date = '1980-04-18 00:00:00';
|
||||
$objCompare->description = 'four';
|
||||
|
||||
$expected[] = clone $objCompare;
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo($expected),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadResult method
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadResult()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('id');
|
||||
$query->from('#__dbtest');
|
||||
$query->where('title=' . self::$driver->quote('Testing2'));
|
||||
|
||||
self::$driver->setQuery($query);
|
||||
$result = self::$driver->loadResult();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo(2),
|
||||
__LINE__
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadRow method
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadRow()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('*');
|
||||
$query->from('#__dbtest');
|
||||
$query->where('description=' . self::$driver->quote('three'));
|
||||
self::$driver->setQuery($query);
|
||||
$result = self::$driver->loadRow();
|
||||
|
||||
$expected = array(3, 'Testing3', '1980-04-18 00:00:00', 'three');
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo($expected),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test loadRowList method
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testLoadRowList()
|
||||
{
|
||||
$query = self::$driver->getQuery(true);
|
||||
$query->select('*');
|
||||
$query->from('#__dbtest');
|
||||
$query->where('description=' . self::$driver->quote('one'));
|
||||
self::$driver->setQuery($query);
|
||||
$result = self::$driver->loadRowList();
|
||||
|
||||
$expected = array(array(1, 'Testing', '1980-04-18 00:00:00', 'one'), array(2, 'Testing2', '1980-04-18 00:00:00', 'one'));
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo($expected),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the JDatabaseDriverPdomysql::execute() method
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testExecute()
|
||||
{
|
||||
self::$driver->setQuery(
|
||||
"REPLACE INTO `jos_dbtest` SET `id` = 5, `title` = 'testTitle', `start_date` = '2014-08-17 00:00:00', `description` = 'testDescription'"
|
||||
);
|
||||
|
||||
$this->assertThat(
|
||||
(bool) self::$driver->execute(),
|
||||
$this->isTrue(),
|
||||
__LINE__
|
||||
);
|
||||
|
||||
$this->assertThat(
|
||||
self::$driver->insertid(),
|
||||
$this->equalTo(5),
|
||||
__LINE__
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the renameTable method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testRenameTable()
|
||||
{
|
||||
$newTableName = 'bak_jos_dbtest';
|
||||
|
||||
self::$driver->renameTable('jos_dbtest', $newTableName);
|
||||
|
||||
// Check name change
|
||||
$tableList = self::$driver->getTableList();
|
||||
|
||||
$this->assertThat(
|
||||
in_array($newTableName, $tableList),
|
||||
$this->isTrue(),
|
||||
__LINE__
|
||||
);
|
||||
|
||||
// Restore initial state
|
||||
self::$driver->renameTable($newTableName, 'jos_dbtest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test select method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testSelect()
|
||||
{
|
||||
$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setUTF method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testSetUTF()
|
||||
{
|
||||
$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the transactionCommit method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testTransactionCommit()
|
||||
{
|
||||
self::$driver->transactionStart();
|
||||
$queryIns = self::$driver->getQuery(true);
|
||||
$queryIns->insert('#__dbtest')
|
||||
->columns('id, title, start_date, description')
|
||||
->values("6, 'testTitle', '1970-01-01', 'testDescription'");
|
||||
|
||||
self::$driver->setQuery($queryIns)->execute();
|
||||
|
||||
self::$driver->transactionCommit();
|
||||
|
||||
/* Check if value is present */
|
||||
$queryCheck = self::$driver->getQuery(true);
|
||||
$queryCheck->select('*')
|
||||
->from('#__dbtest')
|
||||
->where('id = 6');
|
||||
self::$driver->setQuery($queryCheck);
|
||||
$result = self::$driver->loadRow();
|
||||
|
||||
$expected = array('6', 'testTitle', '1970-01-01 00:00:00', 'testDescription');
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->equalTo($expected),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the transactionRollback method, with and without savepoint.
|
||||
*
|
||||
* @param string $toSavepoint Savepoint name to rollback transaction to
|
||||
* @param int $tupleCount Number of tuple found after insertion and rollback
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
* @dataProvider dataTestTransactionRollback
|
||||
*/
|
||||
public function testTransactionRollback($toSavepoint, $tupleCount)
|
||||
{
|
||||
self::$driver->transactionStart();
|
||||
|
||||
/* Try to insert this tuple, inserted only when savepoint != null */
|
||||
$queryIns = self::$driver->getQuery(true);
|
||||
$queryIns->insert('#__dbtest')
|
||||
->columns('id, title, start_date, description')
|
||||
->values("7, 'testRollback', '1970-01-01', 'testRollbackSp'");
|
||||
self::$driver->setQuery($queryIns)->execute();
|
||||
|
||||
/* Create savepoint only if is passed by data provider */
|
||||
if (!is_null($toSavepoint))
|
||||
{
|
||||
self::$driver->transactionStart((boolean) $toSavepoint);
|
||||
}
|
||||
|
||||
/* Try to insert this tuple, always rolled back */
|
||||
$queryIns = self::$driver->getQuery(true);
|
||||
$queryIns->insert('#__dbtest')
|
||||
->columns('id, title, start_date, description')
|
||||
->values("8, 'testRollback', '1972-01-01', 'testRollbackSp'");
|
||||
self::$driver->setQuery($queryIns)->execute();
|
||||
|
||||
self::$driver->transactionRollback((boolean) $toSavepoint);
|
||||
|
||||
/* Release savepoint and commit only if a savepoint exists */
|
||||
if (!is_null($toSavepoint))
|
||||
{
|
||||
self::$driver->transactionCommit();
|
||||
}
|
||||
|
||||
/* Find how many rows have description='testRollbackSp' :
|
||||
* - 0 if a savepoint doesn't exist
|
||||
* - 1 if a savepoint exists
|
||||
*/
|
||||
$queryCheck = self::$driver->getQuery(true);
|
||||
$queryCheck->select('*')
|
||||
->from('#__dbtest')
|
||||
->where("description = 'testRollbackSp'");
|
||||
self::$driver->setQuery($queryCheck);
|
||||
$result = self::$driver->loadRowList();
|
||||
|
||||
$this->assertThat(
|
||||
count($result),
|
||||
$this->equalTo($tupleCount),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test isSupported method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testIsSupported()
|
||||
{
|
||||
$this->assertThat(
|
||||
JDatabaseDriverPdomysql::isSupported(),
|
||||
$this->isTrue(),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test updateObject method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testUpdateObject()
|
||||
{
|
||||
$this->markTestIncomplete('This test has not been implemented yet.');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,593 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.UnitTest
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests the JDatabaseExporterPdomysql class.
|
||||
*
|
||||
* @package Joomla.UnitTest
|
||||
* @subpackage Database
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseExporterPdomysqlTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var object The mocked database object for use by test methods.
|
||||
* @since 3.4
|
||||
*/
|
||||
protected $dbo = null;
|
||||
|
||||
/**
|
||||
* Sets up the testing conditions
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function setup()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Set up the database object mock.
|
||||
$this->dbo = $this->getMock(
|
||||
'JDatabaseDriverPdomysql',
|
||||
array(
|
||||
'getErrorNum',
|
||||
'getPrefix',
|
||||
'getTableColumns',
|
||||
'getTableKeys',
|
||||
'quoteName',
|
||||
'loadObjectList',
|
||||
'setQuery',
|
||||
),
|
||||
array(),
|
||||
'',
|
||||
false
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('getPrefix')
|
||||
->will(
|
||||
$this->returnValue(
|
||||
'jos_'
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('getTableColumns')
|
||||
->will(
|
||||
$this->returnValue(
|
||||
array(
|
||||
(object) array(
|
||||
'Field' => 'id',
|
||||
'Type' => 'int(11) unsigned',
|
||||
'Collation' => null,
|
||||
'Null' => 'NO',
|
||||
'Key' => 'PRI',
|
||||
'Default' => '',
|
||||
'Extra' => 'auto_increment',
|
||||
'Privileges' => 'select,insert,update,references',
|
||||
'Comment' => '',
|
||||
),
|
||||
(object) array(
|
||||
'Field' => 'title',
|
||||
'Type' => 'varchar(255)',
|
||||
'Collation' => 'utf8_general_ci',
|
||||
'Null' => 'NO',
|
||||
'Key' => '',
|
||||
'Default' => '',
|
||||
'Extra' => '',
|
||||
'Privileges' => 'select,insert,update,references',
|
||||
'Comment' => '',
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('getTableKeys')
|
||||
->will(
|
||||
$this->returnValue(
|
||||
array(
|
||||
(object) array(
|
||||
'Table' => 'jos_test',
|
||||
'Non_unique' => '0',
|
||||
'Key_name' => 'PRIMARY',
|
||||
'Seq_in_index' => '1',
|
||||
'Column_name' => 'id',
|
||||
'Collation' => 'A',
|
||||
'Cardinality' => '2695',
|
||||
'Sub_part' => '',
|
||||
'Packed' => '',
|
||||
'Null' => '',
|
||||
'Index_type' => 'BTREE',
|
||||
'Comment' => '',
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('quoteName')
|
||||
->will(
|
||||
$this->returnCallback(
|
||||
array($this, 'callbackQuoteName')
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('setQuery')
|
||||
->will(
|
||||
$this->returnCallback(
|
||||
array($this, 'callbackSetQuery')
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('loadObjectList')
|
||||
->will(
|
||||
$this->returnCallback(
|
||||
array($this, 'callbackLoadObjectList')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the dbo loadObjectList method.
|
||||
*
|
||||
* @return array An array of results based on the setting of the last query.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function callbackLoadObjectList()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the dbo quoteName method.
|
||||
*
|
||||
* @param string $value The value to be quoted.
|
||||
*
|
||||
* @return string The value passed wrapped in MySQL quotes.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function callbackQuoteName($value)
|
||||
{
|
||||
return "`$value`";
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the dbo setQuery method.
|
||||
*
|
||||
* @param string $query The query.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function callbackSetQuery($query)
|
||||
{
|
||||
$this->lastQuery = $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the magic __toString method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function test__toString()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
// Set up the export settings.
|
||||
$instance
|
||||
->setDbo($this->dbo)
|
||||
->from('#__test')
|
||||
->withStructure(true);
|
||||
|
||||
$expecting = '<?xml version="1.0"?>
|
||||
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<database name="">
|
||||
<table_structure name="#__test">
|
||||
<field Field="id" Type="int(11) unsigned" Null="NO" Key="PRI" Default="" Extra="auto_increment" />
|
||||
<field Field="title" Type="varchar(255)" Null="NO" Key="" Default="" Extra="" />
|
||||
<key Table="#__test" Non_unique="0" Key_name="PRIMARY" Seq_in_index="1" Column_name="id" Collation="A" Null="" Index_type="BTREE" Comment="" />
|
||||
</table_structure>
|
||||
</database>
|
||||
</mysqldump>';
|
||||
|
||||
$this->assertThat(
|
||||
preg_replace('/\v/', '', (string) $instance),
|
||||
$this->equalTo(
|
||||
preg_replace('/\v/', '', $expecting)
|
||||
),
|
||||
'__toString has not returned the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the asXml method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testAsXml()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
$result = $instance->asXml();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'asXml must return an object to support chaining.'
|
||||
);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::getValue($instance, 'asFormat'),
|
||||
$this->equalTo('xml'),
|
||||
'The asXml method should set the protected asFormat property to "xml".'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the buildXML method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testBuildXml()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
// Set up the export settings.
|
||||
$instance
|
||||
->setDbo($this->dbo)
|
||||
->from('#__test')
|
||||
->withStructure(true);
|
||||
|
||||
$expecting = '<?xml version="1.0"?>
|
||||
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<database name="">
|
||||
<table_structure name="#__test">
|
||||
<field Field="id" Type="int(11) unsigned" Null="NO" Key="PRI" Default="" Extra="auto_increment" />
|
||||
<field Field="title" Type="varchar(255)" Null="NO" Key="" Default="" Extra="" />
|
||||
<key Table="#__test" Non_unique="0" Key_name="PRIMARY" Seq_in_index="1" Column_name="id" Collation="A" Null="" Index_type="BTREE" Comment="" />
|
||||
</table_structure>
|
||||
</database>
|
||||
</mysqldump>';
|
||||
|
||||
// Replace used to prevent platform conflicts
|
||||
$this->assertThat(
|
||||
preg_replace('/\v/', '', TestReflection::invoke($instance, 'buildXml')),
|
||||
$this->equalTo(
|
||||
preg_replace('/\v/', '', $expecting)
|
||||
),
|
||||
'buildXml has not returned the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the buildXmlStructure method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testBuildXmlStructure()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
// Set up the export settings.
|
||||
$instance
|
||||
->setDbo($this->dbo)
|
||||
->from('#__test')
|
||||
->withStructure(true);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'buildXmlStructure'),
|
||||
$this->equalTo(
|
||||
array(
|
||||
' <table_structure name="#__test">',
|
||||
' <field Field="id" Type="int(11) unsigned" Null="NO" Key="PRI" Default="" Extra="auto_increment" />',
|
||||
' <field Field="title" Type="varchar(255)" Null="NO" Key="" Default="" Extra="" />',
|
||||
' <key Table="#__test" Non_unique="0" Key_name="PRIMARY" Seq_in_index="1" Column_name="id" Collation="A" ' .
|
||||
'Null="" Index_type="BTREE" Comment="" />',
|
||||
' </table_structure>'
|
||||
)
|
||||
),
|
||||
'buildXmlStructure has not returned the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the check method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testCheckWithNoDbo()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$instance->check();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Exception expected.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(
|
||||
'Check method should throw exception if DBO not set'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the check method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testCheckWithNoTables()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
try
|
||||
{
|
||||
$instance->check();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Exception expected.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(
|
||||
'Check method should throw exception if DBO not set'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the check method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testCheckWithGoodInput()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
$instance->from('foobar');
|
||||
|
||||
try
|
||||
{
|
||||
$result = $instance->check();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'check must return an object to support chaining.'
|
||||
);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$this->fail(
|
||||
'Check method should not throw exception with good setup: ' . $e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the from method with bad input.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testFromWithBadInput()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$instance->from(new stdClass);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Exception expected.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(
|
||||
'From method should thrown an exception if argument is not a string or array.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the from method with expected good inputs.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testFromWithGoodInput()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$result = $instance->from('jos_foobar');
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'from must return an object to support chaining.'
|
||||
);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::getValue($instance, 'from'),
|
||||
$this->equalTo(array('jos_foobar')),
|
||||
'The from method should convert a string input to an array.'
|
||||
);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$this->fail(
|
||||
'From method should not throw exception with good input: ' . $e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the method getGenericTableName method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetGenericTableName()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getGenericTableName', 'jos_test'),
|
||||
$this->equalTo('#__test'),
|
||||
'The testGetGenericTableName should replace the database prefix with #__.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the setDbo method with the wrong type of class.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testSetDboWithBadInput()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$instance->setDbo(new stdClass);
|
||||
}
|
||||
catch (PHPUnit_Framework_Error $e)
|
||||
{
|
||||
// Expecting the error, so just ignore it.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(
|
||||
'setDbo requires a JDatabaseDriverPdomysql object and should throw an exception.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the setDbo method with the wrong type of class.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testSetDboWithGoodInput()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$result = $instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'setDbo must return an object to support chaining.'
|
||||
);
|
||||
}
|
||||
catch (PHPUnit_Framework_Error $e)
|
||||
{
|
||||
// Unknown error has occurred.
|
||||
$this->fail(
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the withStructure method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testWithStructure()
|
||||
{
|
||||
$instance = new JDatabaseExporterPdomysql;
|
||||
|
||||
$result = $instance->withStructure();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'withStructure must return an object to support chaining.'
|
||||
);
|
||||
|
||||
$options = TestReflection::getValue($instance, 'options');
|
||||
|
||||
$this->assertThat(
|
||||
$options->withStructure,
|
||||
$this->isTrue(),
|
||||
'The default use of withStructure should result in true.'
|
||||
);
|
||||
|
||||
$instance->withStructure(true);
|
||||
|
||||
$options = TestReflection::getValue($instance, 'options');
|
||||
|
||||
$this->assertThat(
|
||||
$options->withStructure,
|
||||
$this->isTrue(),
|
||||
'The explicit use of withStructure with true should result in true.'
|
||||
);
|
||||
|
||||
$instance->withStructure(false);
|
||||
|
||||
$options = TestReflection::getValue($instance, 'options');
|
||||
|
||||
$this->assertThat(
|
||||
$options->withStructure,
|
||||
$this->isFalse(),
|
||||
'The explicit use of withStructure with false should result in false.'
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,871 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.UnitTest
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests the JDatabaseImporterPdomysql class.
|
||||
*
|
||||
* @package Joomla.UnitTest
|
||||
* @subpackage Database
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseImporterPdomysqlTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @var object The mocked database object for use by test methods.
|
||||
* @since 3.4
|
||||
*/
|
||||
protected $dbo = null;
|
||||
|
||||
/**
|
||||
* @var string The last query sent to the dbo setQuery method.
|
||||
* @since 3.4
|
||||
*/
|
||||
protected $lastQuery = '';
|
||||
|
||||
/**
|
||||
* @var array Selected sample data for tests.
|
||||
* @since 3.4
|
||||
*/
|
||||
protected $sample = array(
|
||||
'xml-id-field' =>
|
||||
'<field Field="id" Type="int(11) unsigned" Null="NO" Key="PRI" Default="" Extra="auto_increment" />',
|
||||
'xml-title-field' =>
|
||||
'<field Field="title" Type="varchar(50)" Null="NO" Key="" Default="" Extra="" />',
|
||||
'xml-body-field' =>
|
||||
'<field Field="body" Type="mediumtext" Null="NO" Key="" Default="" Extra="" />',
|
||||
'xml-primary-key' =>
|
||||
'<key Table="#__test" Non_unique="0" Key_name="PRIMARY" Seq_in_index="1" Column_name="id" Collation="A" Null="" Index_type="BTREE" Comment="" />',
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets up the testing conditions
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function setup()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Set up the database object mock.
|
||||
$this->dbo = $this->getMock(
|
||||
'JDatabaseDriverPdomysql',
|
||||
array(
|
||||
'getErrorNum',
|
||||
'getPrefix',
|
||||
'getTableColumns',
|
||||
'getTableKeys',
|
||||
'quoteName',
|
||||
'loadObjectList',
|
||||
'quote',
|
||||
'setQuery',
|
||||
),
|
||||
array(),
|
||||
'',
|
||||
false
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('getPrefix')
|
||||
->will(
|
||||
$this->returnValue(
|
||||
'jos_'
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('getTableColumns')
|
||||
->will(
|
||||
$this->returnValue(
|
||||
array(
|
||||
'id' => (object) array(
|
||||
'Field' => 'id',
|
||||
'Type' => 'int(11) unsigned',
|
||||
'Collation' => null,
|
||||
'Null' => 'NO',
|
||||
'Key' => 'PRI',
|
||||
'Default' => '',
|
||||
'Extra' => 'auto_increment',
|
||||
'Privileges' => 'select,insert,update,references',
|
||||
'Comment' => '',
|
||||
),
|
||||
'title' => (object) array(
|
||||
'Field' => 'title',
|
||||
'Type' => 'varchar(255)',
|
||||
'Collation' => 'utf8_general_ci',
|
||||
'Null' => 'NO',
|
||||
'Key' => '',
|
||||
'Default' => '',
|
||||
'Extra' => '',
|
||||
'Privileges' => 'select,insert,update,references',
|
||||
'Comment' => '',
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('getTableKeys')
|
||||
->will(
|
||||
$this->returnValue(
|
||||
array(
|
||||
(object) array(
|
||||
'Table' => 'jos_test',
|
||||
'Non_unique' => '0',
|
||||
'Key_name' => 'PRIMARY',
|
||||
'Seq_in_index' => '1',
|
||||
'Column_name' => 'id',
|
||||
'Collation' => 'A',
|
||||
'Cardinality' => '2695',
|
||||
'Sub_part' => '',
|
||||
'Packed' => '',
|
||||
'Null' => '',
|
||||
'Index_type' => 'BTREE',
|
||||
'Comment' => '',
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('quoteName')
|
||||
->will(
|
||||
$this->returnCallback(
|
||||
array($this, 'callbackQuoteName')
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('quote')
|
||||
->will(
|
||||
$this->returnCallback(
|
||||
array($this, 'callbackQuote')
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('setQuery')
|
||||
->will(
|
||||
$this->returnCallback(
|
||||
array($this, 'callbackSetQuery')
|
||||
)
|
||||
);
|
||||
|
||||
$this->dbo->expects(
|
||||
$this->any()
|
||||
)
|
||||
->method('loadObjectList')
|
||||
->will(
|
||||
$this->returnCallback(
|
||||
array($this, 'callbackLoadObjectList')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the dbo loadObjectList method.
|
||||
*
|
||||
* @return array An array of results based on the setting of the last query.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function callbackLoadObjectList()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the dbo quote method.
|
||||
*
|
||||
* @param string $value The value to be quoted.
|
||||
*
|
||||
* @return string The value passed wrapped in MySQL quotes.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function callbackQuote($value)
|
||||
{
|
||||
return "'$value'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the dbo quoteName method.
|
||||
*
|
||||
* @param string $value The value to be quoted.
|
||||
*
|
||||
* @return string The value passed wrapped in MySQL quotes.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function callbackQuoteName($value)
|
||||
{
|
||||
return "`$value`";
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for the dbo setQuery method.
|
||||
*
|
||||
* @param string $query The query.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function callbackSetQuery($query)
|
||||
{
|
||||
$this->lastQuery = $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for the testGetAlterTableSQL test.
|
||||
*
|
||||
* @return array Each array element must be an array with 3 elements: SimpleXMLElement field, expected result, error message.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function dataGetAlterTableSQL()
|
||||
{
|
||||
$f1 = '<field Field="id" Type="int(11) unsigned" Null="NO" Key="PRI" Default="" Extra="auto_increment" />';
|
||||
$f2 = '<field Field="title" Type="varchar(255)" Null="NO" Key="" Default="" Extra="" />';
|
||||
$f3 = '<field Field="alias" Type="varchar(255)" Null="NO" Key="" Default="" Extra="" />';
|
||||
|
||||
$k1 = '<key Table="#__test" Non_unique="0" Key_name="PRIMARY" Seq_in_index="1"' .
|
||||
' Column_name="id" Collation="A" Null="" Index_type="BTREE" Comment="" />';
|
||||
$k2 = '<key Table="#__test" Non_unique="0" Key_name="idx_title" Seq_in_index="1"' .
|
||||
' Column_name="title" Collation="A" Null="" Index_type="BTREE" Comment="" />';
|
||||
|
||||
return array(
|
||||
array(
|
||||
new SimpleXmlElement('<table_structure name="#__test">' . $f1 . $f2 . $k1 . '</table_structure>'),
|
||||
array(),
|
||||
'getAlterTableSQL should not change anything.'
|
||||
),
|
||||
array(
|
||||
new SimpleXmlElement('<table_structure name="#__test">' . $f1 . $f2 . $f3 . $k1 . '</table_structure>'),
|
||||
array(
|
||||
"ALTER TABLE `jos_test` ADD COLUMN `alias` varchar(255) NOT NULL DEFAULT ''",
|
||||
),
|
||||
'getAlterTableSQL should add the new alias column.'
|
||||
),
|
||||
array(
|
||||
new SimpleXmlElement('<table_structure name="#__test">' . $f1 . $f2 . $k1 . $k2 . '</table_structure>'),
|
||||
array(
|
||||
"ALTER TABLE `jos_test` ADD UNIQUE KEY `idx_title` (`title`)",
|
||||
),
|
||||
'getAlterTableSQL should add the new key.'
|
||||
),
|
||||
array(
|
||||
new SimpleXmlElement('<table_structure name="#__test">' . $f1 . $k1 . '</table_structure>'),
|
||||
array(
|
||||
"ALTER TABLE `jos_test` DROP COLUMN `title`",
|
||||
),
|
||||
'getAlterTableSQL should remove the title column.'
|
||||
),
|
||||
array(
|
||||
new SimpleXmlElement('<table_structure name="#__test">' . $f1 . $f2 . '</table_structure>'),
|
||||
array(
|
||||
"ALTER TABLE `jos_test` DROP PRIMARY KEY",
|
||||
),
|
||||
'getAlterTableSQL should drop the old primary key.'
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for the testGetColumnSQL test.
|
||||
*
|
||||
* @return array Each array element must be an array with 3 elements: SimpleXMLElement field, expected result, error message.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function dataGetColumnSQL()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
new SimpleXmlElement(
|
||||
$this->sample['xml-id-field']
|
||||
),
|
||||
"`id` int(11) unsigned NOT NULL DEFAULT '' AUTO_INCREMENT",
|
||||
'Typical primary key field',
|
||||
),
|
||||
array(
|
||||
new SimpleXmlElement(
|
||||
$this->sample['xml-title-field']
|
||||
),
|
||||
"`title` varchar(50) NOT NULL DEFAULT ''",
|
||||
'Typical text field',
|
||||
),
|
||||
array(
|
||||
new SimpleXmlElement(
|
||||
$this->sample['xml-body-field']
|
||||
),
|
||||
"`body` mediumtext NOT NULL",
|
||||
'Typical blob field',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for the testGetColumnSQL test.
|
||||
*
|
||||
* @return array Each array element must be an array with 3 elements: SimpleXMLElement field, expected result, error message.
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function dataGetKeySQL()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
// Keys come in arrays.
|
||||
array(
|
||||
new SimpleXmlElement(
|
||||
$this->sample['xml-primary-key']
|
||||
),
|
||||
),
|
||||
"primary key (`id`)",
|
||||
'Typical primary key index',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the asXml method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testAsXml()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
|
||||
$result = $instance->asXml();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'asXml must return an object to support chaining.'
|
||||
);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::getValue($instance, 'asFormat'),
|
||||
$this->equalTo('xml'),
|
||||
'The asXml method should set the protected asFormat property to "xml".'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the check method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testCheckWithNoDbo()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$instance->check();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Exception expected.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(
|
||||
'Check method should throw exception if DBO not set'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the check method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testCheckWithNoFrom()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
try
|
||||
{
|
||||
$instance->check();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Exception expected.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(
|
||||
'Check method should throw exception if DBO not set'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the check method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testCheckWithGoodInput()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
$instance->from('foobar');
|
||||
|
||||
try
|
||||
{
|
||||
$result = $instance->check();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'check must return an object to support chaining.'
|
||||
);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$this->fail(
|
||||
'Check method should not throw exception with good setup: ' . $e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the from method with expected good inputs.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testFromWithGoodInput()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$result = $instance->from('foobar');
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'from must return an object to support chaining.'
|
||||
);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::getValue($instance, 'from'),
|
||||
$this->equalTo('foobar'),
|
||||
'The from method did not store the value as expected.'
|
||||
);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$this->fail(
|
||||
'From method should not throw exception with good input: ' . $e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAddColumnSQL method.
|
||||
*
|
||||
* Note that combinations of fields is tested in testGetColumnSQL.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetAddColumnSQL()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getAddColumnSql', 'jos_test', new SimpleXmlElement($this->sample['xml-title-field'])),
|
||||
$this->equalTo(
|
||||
"ALTER TABLE `jos_test` ADD COLUMN `title` varchar(50) NOT NULL DEFAULT ''"
|
||||
),
|
||||
'testGetAddColumnSQL did not yield the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAddKeySQL method.
|
||||
*
|
||||
* Note that combinations of keys is tested in testGetKeySQL.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetAddKeySQL()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getAddKeySQL', 'jos_test', array(new SimpleXmlElement($this->sample['xml-primary-key']))),
|
||||
$this->equalTo(
|
||||
"ALTER TABLE `jos_test` ADD PRIMARY KEY (`id`)"
|
||||
),
|
||||
'testGetAddKeySQL did not yield the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getAlterTableSQL method.
|
||||
*
|
||||
* @param string $structure @todo
|
||||
* @param string $expected @todo
|
||||
* @param string $message @todo
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @dataProvider dataGetAlterTableSQL
|
||||
*/
|
||||
public function testGetAlterTableSQL($structure, $expected, $message)
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getAlterTableSQL', $structure),
|
||||
$this->equalTo(
|
||||
$expected
|
||||
),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getChangeColumnSQL method.
|
||||
*
|
||||
* Note that combinations of fields is tested in testGetColumnSQL.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetChangeColumnSQL()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getChangeColumnSQL', 'jos_test', new SimpleXmlElement($this->sample['xml-title-field'])),
|
||||
$this->equalTo(
|
||||
"ALTER TABLE `jos_test` CHANGE COLUMN `title` `title` varchar(50) NOT NULL DEFAULT ''"
|
||||
),
|
||||
'getChangeColumnSQL did not yield the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getColumnSQL method.
|
||||
*
|
||||
* @param string $field @todo
|
||||
* @param string $expected The expected result from the getColumnSQL method.
|
||||
* @param string $message The error message to display if the result does not match the expected value.
|
||||
*
|
||||
* @internal param \SimpleXmlElement $xml The database field as an object.
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @dataProvider dataGetColumnSQL
|
||||
*/
|
||||
public function testGetColumnSQL($field, $expected, $message)
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
strtolower(TestReflection::invoke($instance, 'getColumnSQL', $field)),
|
||||
$this->equalTo(strtolower($expected)),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getDropColumnSQL method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetDropColumnSQL()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getDropColumnSQL', 'jos_test', 'title'),
|
||||
$this->equalTo(
|
||||
"ALTER TABLE `jos_test` DROP COLUMN `title`"
|
||||
),
|
||||
'getDropColumnSQL did not yield the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getDropKeySQL method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetDropKeySQL()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getDropKeySQL', 'jos_test', 'idx_title'),
|
||||
$this->equalTo(
|
||||
"ALTER TABLE `jos_test` DROP KEY `idx_title`"
|
||||
),
|
||||
'getDropKeySQL did not yield the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getDropPrimaryKeySQL method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetDropPrimaryKeySQL()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getDropPrimaryKeySQL', 'jos_test'),
|
||||
$this->equalTo(
|
||||
"ALTER TABLE `jos_test` DROP PRIMARY KEY"
|
||||
),
|
||||
'getDropPrimaryKeySQL did not yield the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getKeyLookup method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetKeyLookup()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
|
||||
$o1 = (object) array('Key_name' => 'id', 'foo' => 'bar1');
|
||||
$o2 = (object) array('Key_name' => 'id', 'foo' => 'bar2');
|
||||
$o3 = (object) array('Key_name' => 'title', 'foo' => 'bar3');
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getKeyLookup', array($o1, $o2, $o3)),
|
||||
$this->equalTo(
|
||||
array(
|
||||
'id' => array($o1, $o2),
|
||||
'title' => array($o3)
|
||||
)
|
||||
),
|
||||
'getKeyLookup, using array input, did not yield the expected result.'
|
||||
);
|
||||
|
||||
$o1 = new SimpleXmlElement('<key Key_name="id" foo="bar1" />');
|
||||
$o2 = new SimpleXmlElement('<key Key_name="id" foo="bar2" />');
|
||||
$o3 = new SimpleXmlElement('<key Key_name="title" foo="bar3" />');
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getKeyLookup', array($o1, $o2, $o3)),
|
||||
$this->equalTo(
|
||||
array(
|
||||
'id' => array($o1, $o2),
|
||||
'title' => array($o3)
|
||||
)
|
||||
),
|
||||
'getKeyLookup, using SimpleXmlElement input, did not yield the expected result.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getKeySQL method.
|
||||
*
|
||||
* @param string $field @todo
|
||||
* @param string $expected The expected result from the getKeySQL method.
|
||||
* @param string $message The error message to display if the result does not match the expected value.
|
||||
*
|
||||
* @internal param \SimpleXmlElement $xml The database key as an object.
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*
|
||||
* @dataProvider dataGetKeySQL
|
||||
*/
|
||||
public function testGetKeySQL($field, $expected, $message)
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
strtolower(TestReflection::invoke($instance, 'getKeySQL', $field)),
|
||||
$this->equalTo(strtolower($expected)),
|
||||
$message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getRealTableName method with the wrong type of class.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testGetRealTableName()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
$instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
TestReflection::invoke($instance, 'getRealTableName', '#__test'),
|
||||
$this->equalTo('jos_test'),
|
||||
'getRealTableName should return the name of the table with #__ converted to the database prefix.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the setDbo method with the wrong type of class.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testSetDboWithBadInput()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$instance->setDbo(new stdClass);
|
||||
}
|
||||
catch (PHPUnit_Framework_Error $e)
|
||||
{
|
||||
// Expecting the error, so just ignore it.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fail(
|
||||
'setDbo requires a JDatabaseDriverPdomysql object and should throw an exception.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the setDbo method with the wrong type of class.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testSetDboWithGoodInput()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
|
||||
try
|
||||
{
|
||||
$result = $instance->setDbo($this->dbo);
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'setDbo must return an object to support chaining.'
|
||||
);
|
||||
|
||||
}
|
||||
catch (PHPUnit_Framework_Error $e)
|
||||
{
|
||||
// Unknown error has occurred.
|
||||
$this->fail(
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the withStructure method.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testWithStructure()
|
||||
{
|
||||
$instance = new JDatabaseImporterPdomysql;
|
||||
|
||||
$result = $instance->withStructure();
|
||||
|
||||
$this->assertThat(
|
||||
$result,
|
||||
$this->identicalTo($instance),
|
||||
'withStructure must return an object to support chaining.'
|
||||
);
|
||||
|
||||
$options = TestReflection::getValue($instance, 'options');
|
||||
|
||||
$this->assertThat(
|
||||
$options->withStructure,
|
||||
$this->isTrue(),
|
||||
'The default use of withStructure should result in true.'
|
||||
);
|
||||
|
||||
$instance->withStructure(true);
|
||||
|
||||
$options = TestReflection::getValue($instance, 'options');
|
||||
|
||||
$this->assertThat(
|
||||
$options->withStructure,
|
||||
$this->isTrue(),
|
||||
'The explicit use of withStructure with true should result in true.'
|
||||
);
|
||||
|
||||
$instance->withStructure(false);
|
||||
|
||||
$options = TestReflection::getValue($instance, 'options');
|
||||
|
||||
$this->assertThat(
|
||||
$options->withStructure,
|
||||
$this->isFalse(),
|
||||
'The explicit use of withStructure with false should result in false.'
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
/**
|
||||
* @package Joomla.UnitTest
|
||||
* @subpackage Database
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test class for JDatabaseIteratorPdomysql.
|
||||
*
|
||||
* @package Joomla.UnitTest
|
||||
* @subpackage Database
|
||||
* @since 3.4
|
||||
*/
|
||||
class JDatabaseIteratorPdomysqlTest extends TestCaseDatabasePdomysql
|
||||
{
|
||||
/**
|
||||
* Data provider for the testForEach method
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function casesForEachData()
|
||||
{
|
||||
return array(
|
||||
// Testing 'stdClass' type without specific index, offset or limit
|
||||
array(
|
||||
'title',
|
||||
'#__dbtest',
|
||||
null,
|
||||
'stdClass',
|
||||
0,
|
||||
0,
|
||||
array(
|
||||
(object) array('title' => 'Testing'),
|
||||
(object) array('title' => 'Testing2'),
|
||||
(object) array('title' => 'Testing3'),
|
||||
(object) array('title' => 'Testing4')
|
||||
),
|
||||
null
|
||||
),
|
||||
|
||||
// Testing 'stdClass' type, limit=2 without specific index or offset
|
||||
array(
|
||||
'title',
|
||||
'#__dbtest',
|
||||
null,
|
||||
'stdClass',
|
||||
2,
|
||||
0,
|
||||
array(
|
||||
(object) array('title' => 'Testing'),
|
||||
(object) array('title' => 'Testing2')
|
||||
),
|
||||
null
|
||||
),
|
||||
|
||||
// Testing 'stdClass' type, offset=2 without specific index or limit
|
||||
array(
|
||||
'title',
|
||||
'#__dbtest',
|
||||
null,
|
||||
'stdClass',
|
||||
20,
|
||||
2,
|
||||
array(
|
||||
(object) array('title' => 'Testing3'),
|
||||
(object) array('title' => 'Testing4')
|
||||
),
|
||||
null
|
||||
),
|
||||
|
||||
// Testing 'stdClass' type, index='title' without specific offset or limit
|
||||
array(
|
||||
'title, id',
|
||||
'#__dbtest',
|
||||
'title',
|
||||
'stdClass',
|
||||
0,
|
||||
0,
|
||||
array(
|
||||
'Testing' => (object) array('title' => 'Testing', 'id' => '1'),
|
||||
'Testing2' => (object) array('title' => 'Testing2', 'id' => '2'),
|
||||
'Testing3' => (object) array('title' => 'Testing3', 'id' => '3'),
|
||||
'Testing4' => (object) array('title' => 'Testing4', 'id' => '4')
|
||||
),
|
||||
null,
|
||||
),
|
||||
|
||||
// Testing 'UnexistingClass' type, index='title' without specific offset or limit
|
||||
array(
|
||||
'title',
|
||||
'#__dbtest',
|
||||
'title',
|
||||
'UnexistingClass',
|
||||
0,
|
||||
0,
|
||||
array(),
|
||||
'InvalidArgumentException',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test foreach control
|
||||
*
|
||||
* @param string $select Fields to select
|
||||
* @param string $from Table to search for
|
||||
* @param string $column The column to use as a key.
|
||||
* @param string $class The class on which to bind the result rows.
|
||||
* @param integer $limit The result set record limit.
|
||||
* @param integer $offset The result set record offset.
|
||||
* @param array $expected Array of expected results
|
||||
* @param mixed $exception Exception thrown
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider casesForEachData
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testForEach($select, $from, $column, $class, $limit, $offset, $expected, $exception)
|
||||
{
|
||||
if ($exception)
|
||||
{
|
||||
$this->setExpectedException($exception);
|
||||
}
|
||||
|
||||
self::$driver->setQuery(self::$driver->getQuery(true)->select($select)->from($from), $offset, $limit);
|
||||
$iterator = self::$driver->getIterator($column, $class);
|
||||
|
||||
// Run the Iterator pattern
|
||||
$this->assertThat(
|
||||
iterator_to_array($iterator),
|
||||
$this->equalTo($expected),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test count
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.4
|
||||
*/
|
||||
public function testCount()
|
||||
{
|
||||
self::$driver->setQuery(self::$driver->getQuery(true)->select('title')->from('#__dbtest'));
|
||||
|
||||
$this->assertThat(
|
||||
count(self::$driver->getIterator()),
|
||||
$this->equalTo(4),
|
||||
__LINE__
|
||||
);
|
||||
|
||||
self::$driver->setQuery(self::$driver->getQuery(true)->select('title')->from('#__dbtest'), 0, 2);
|
||||
|
||||
$this->assertThat(
|
||||
count(self::$driver->getIterator()),
|
||||
$this->equalTo(2),
|
||||
__LINE__
|
||||
);
|
||||
|
||||
self::$driver->setQuery(self::$driver->getQuery(true)->select('title')->from('#__dbtest'), 3, 2);
|
||||
|
||||
$this->assertThat(
|
||||
count(self::$driver->getIterator()),
|
||||
$this->equalTo(1),
|
||||
__LINE__
|
||||
);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
<php>
|
||||
<const name="JTEST_DATABASE_MYSQL_DSN" value="host=localhost;dbname=joomla_ut;user=root;pass=" />
|
||||
<const name="JTEST_DATABASE_MYSQLI_DSN" value="host=localhost;dbname=joomla_ut;user=root;pass=" />
|
||||
<const name="JTEST_DATABASE_PDO_MYSQL_DSN" value="host=localhost;dbname=joomla_ut;user=root;pass=" />
|
||||
<const name="JTEST_DATABASE_POSTGRESQL_DSN" value="host=localhost;port=5432;dbname=joomla_ut;user=postgres;pass=" />
|
||||
</php>
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user