Skip to content

Instantly share code, notes, and snippets.

@siran
Last active November 16, 2016 09:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save siran/77d65f9375cf7b787c83 to your computer and use it in GitHub Desktop.
Save siran/77d65f9375cf7b787c83 to your computer and use it in GitHub Desktop.
<?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;
JLoader::register('JDatabaseMySQL', dirname(__FILE__) . '/mysql.php');
JLoader::register('JDatabaseQueryMySQLi', dirname(__FILE__) . '/mysqliquery.php');
JLoader::register('JDatabaseExporterMySQLi', dirname(__FILE__) . '/mysqliexporter.php');
JLoader::register('JDatabaseImporterMySQLi', dirname(__FILE__) . '/mysqliimporter.php');
/**
* MySQLi database driver
*
* @package Joomla.Platform
* @subpackage Database
* @see http://php.net/manual/en/book.mysqli.php
* @since 11.1
*/
class JDatabaseMySQLi_amazon extends JDatabaseMySQL
{
/**
* The name of the database driver.
*
* @var string
* @since 11.1
*/
public $name = 'mysqli_amazon';
public $host_read = 'my.read.endpoint';
/**
* Constructor.
*
* @param array $options List of options used to configure the connection
*
* @since 11.1
*/
protected function __construct($options)
{
if (!empty($this->host_read)) {
$options['host_read'] = $this->host_read;
}
// Get some basic values from the options.
$options['host'] = (isset($options['host'])) ? $options['host'] : 'localhost';
$options['host_read'] = (isset($options['host_read'])) ? $options['host_read'] : 'localhost';
$options['user'] = (isset($options['user'])) ? $options['user'] : 'root';
$options['password'] = (isset($options['password'])) ? $options['password'] : '';
$options['database'] = (isset($options['database'])) ? $options['database'] : '';
$options['select'] = (isset($options['select'])) ? (bool) $options['select'] : true;
$options['port'] = null;
$options['socket'] = null;
/*
* Unlike mysql_connect(), mysqli_connect() takes the port and socket as separate arguments. Therefore, we
* have to extract them from the host string.
*/
$tmp = substr(strstr($options['host'], ':'), 1);
if (!empty($tmp))
{
// Get the port number or socket name
if (is_numeric($tmp))
{
$options['port'] = $tmp;
}
else
{
$options['socket'] = $tmp;
}
// Extract the host name only
$options['host'] = substr($options['host'], 0, strlen($options['host']) - (strlen($tmp) + 1));
// Extract the host name for read queries only
$options['host_read'] = substr($options['host_read'], 0, strlen($options['host_read']) - (strlen($tmp) + 1));
// This will take care of the following notation: ":3306"
if ($options['host'] == '')
{
$options['host'] = 'localhost';
}
if ($options['host_read'] == '')
{
$options['host_read'] = 'localhost';
}
}
// Make sure the MySQLi extension for PHP is installed and enabled.
if (!function_exists('mysqli_connect'))
{
// Legacy error handling switch based on the JError::$legacy switch.
// @deprecated 12.1
if (JError::$legacy)
{
$this->errorNum = 1;
$this->errorMsg = JText::_('JLIB_DATABASE_ERROR_ADAPTER_MYSQLI');
return;
}
else
{
throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_ADAPTER_MYSQLI'));
}
}
$this->connection = @mysqli_connect(
$options['host'], $options['user'], $options['password'], null, $options['port'], $options['socket']
);
$this->connection_read = mysqli_connect(
$options['host_read'], $options['user'], $options['password'], null, $options['port'], $options['socket']
);
// Attempt to connect to the server.
if (!$this->connection)
{
// Legacy error handling switch based on the JError::$legacy switch.
// @deprecated 12.1
if (JError::$legacy)
{
$this->errorNum = 2;
$this->errorMsg = JText::_('JLIB_DATABASE_ERROR_CONNECT_MYSQL');
return;
}
else
{
throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_CONNECT_MYSQL'));
}
}
if (!$this->connection_read)
{
// Legacy error handling switch based on the JError::$legacy switch.
// @deprecated 12.1
if (JError::$legacy)
{
$this->errorNum = 2;
$this->errorMsg = JText::_('JLIB_DATABASE_ERROR_CONNECT_READ_MYSQL');
return;
}
else
{
throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_CONNECT_READ_MYSQL'));
}
}
// Finalize initialisation
JDatabase::__construct($options);
// Set sql_mode to non_strict mode
mysqli_query($this->connection, "SET @@SESSION.sql_mode = '';");
mysqli_query($this->connection_read, "SET @@SESSION.sql_mode = '';");
// If auto-select is enabled select the given database.
if ($options['select'] && !empty($options['database']))
{
$this->select($options['database']);
}
}
/**
* Destructor.
*
* @since 11.1
*/
public function __destruct()
{
if (is_callable(array($this->connection, 'close')))
{
mysqli_close($this->connection);
}
if (is_callable(array($this->connection_read, 'close')))
{
mysqli_close($this->connection_read);
}
}
/**
* Method to escape a string for usage in an SQL statement.
*
* @param string $text The string to be escaped.
* @param boolean $extra Optional parameter to provide extra escaping.
*
* @return string The escaped string.
*
* @since 11.1
*/
public function escape($text, $extra = false)
{
if (preg_match('/select/i', $text )) {
$result = mysqli_real_escape_string($this->connection_read, $text);
} else {
$result = mysqli_real_escape_string($this->getConnection(), $text);
}
if ($extra)
{
$result = addcslashes($result, '%_');
}
return $result;
}
/**
* Test to see if the MySQL connector is available.
*
* @return boolean True on success, false otherwise.
*
* @since 11.1
*/
public static function test()
{
return (function_exists('mysqli_connect'));
}
/**
* Determines if the connection to the server is active.
*
* @return boolean True if connected to the database engine.
*
* @since 11.1
*/
public function connected()
{
if (is_object($this->connection))
{
return mysqli_ping($this->connection);
}
return false;
}
/**
* Get the number of affected rows for the previous executed SQL statement.
*
* @return integer The number of affected rows.
*
* @since 11.1
*/
public function getAffectedRows()
{
return mysqli_affected_rows($this->connection) ? mysqli_affected_rows($this->connection) : mysqli_affected_rows($this->connection_read);
}
/**
* Gets an exporter class object.
*
* @return JDatabaseExporterMySQLi An exporter object.
*
* @since 11.1
* @throws JDatabaseException
*/
public function getExporter()
{
// Make sure we have an exporter class for this driver.
if (!class_exists('JDatabaseExporterMySQLi'))
{
throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_MISSING_EXPORTER'));
}
$o = new JDatabaseExporterMySQLi;
$o->setDbo($this);
return $o;
}
/**
* Gets an importer class object.
*
* @return JDatabaseImporterMySQLi An importer object.
*
* @since 11.1
* @throws JDatabaseException
*/
public function getImporter()
{
// Make sure we have an importer class for this driver.
if (!class_exists('JDatabaseImporterMySQLi'))
{
throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_MISSING_IMPORTER'));
}
$o = new JDatabaseImporterMySQLi;
$o->setDbo($this);
return $o;
}
/**
* Get the number of returned rows for the previous executed SQL statement.
*
* @param resource $cursor An optional database cursor resource to extract the row count from.
*
* @return integer The number of returned rows.
*
* @since 11.1
*/
public function getNumRows($cursor = null)
{
return mysqli_num_rows($cursor ? $cursor : $this->cursor);
}
/**
* Get the current or query, or new JDatabaseQuery object.
*
* @param boolean $new False to return the last query set, True to return a new JDatabaseQuery object.
*
* @return mixed The current value of the internal SQL variable or a new JDatabaseQuery object.
*
* @since 11.1
* @throws JDatabaseException
*/
public function getQuery($new = false)
{
if ($new)
{
// Make sure we have a query class for this driver.
if (!class_exists('JDatabaseQueryMySQLi'))
{
throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_MISSING_QUERY'));
}
return new JDatabaseQueryMySQLi($this);
}
else
{
return $this->sql;
}
}
/**
* Get the version of the database connector.
*
* @return string The database connector version.
*
* @since 11.1
*/
public function getVersion()
{
return mysqli_get_server_info($this->connection);
}
/**
* Determines if the database engine supports UTF-8 character encoding.
*
* @return boolean True if supported.
*
* @since 11.1
* @deprecated 12.1
*/
public function hasUTF()
{
JLog::add('JDatabaseMySQLi::hasUTF() is deprecated.', JLog::WARNING, 'deprecated');
return true;
}
/**
* Method to get the auto-incremented value from the last INSERT statement.
*
* @return integer The value of the auto-increment field from the last inserted row.
*
* @since 11.1
*/
public function insertid()
{
return mysqli_insert_id($this->connection);
}
/**
* Execute the SQL statement.
*
* @return mixed A database cursor resource on success, boolean false on failure.
*
* @since 11.1
* @throws JDatabaseException
*/
public function execute()
{
if (!is_object($this->connection))
{
// Legacy error handling switch based on the JError::$legacy switch.
// @deprecated 12.1
if (JError::$legacy)
{
if ($this->debug)
{
JError::raiseError(500, 'JDatabaseMySQLi::query: ' . $this->errorNum . ' - ' . $this->errorMsg);
}
return false;
}
else
{
JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'database');
throw new JDatabaseException($this->errorMsg, $this->errorNum);
}
}
// Take a local copy so that we don't modify the original query and cause issues later
$sql = $this->replacePrefix((string) $this->sql);
if ($this->limit > 0 || $this->offset > 0)
{
$sql .= ' LIMIT ' . $this->offset . ', ' . $this->limit;
}
// If debugging is enabled then let's log the query.
if ($this->debug)
{
// Increment the query counter and add the query to the object queue.
$this->count++;
$this->log[] = $sql;
JLog::add($sql, JLog::DEBUG, 'databasequery');
}
// Reset the error values.
$this->errorNum = 0;
$this->errorMsg = '';
// Execute the query.
if (preg_match('/select/i', $sql )) {
$connection_amazon = $this->connection_read;
} else {
$connection_amazon = $this->connection;
}
$this->cursor = mysqli_query($connection_amazon, $sql);
// If an error occurred handle it.
if (!$this->cursor)
{
$this->errorNum = (int) mysqli_errno($connection_amazon);
$this->errorMsg = (string) mysqli_error($connection_amazon) . ' SQL=' . $sql;
// Legacy error handling switch based on the JError::$legacy switch.
// @deprecated 12.1
if (JError::$legacy)
{
if ($this->debug)
{
JError::raiseError(500, 'JDatabaseMySQLi::query: ' . $this->errorNum . ' - ' . $this->errorMsg);
}
return false;
}
else
{
JLog::add(JText::sprintf('JLIB_DATABASE_QUERY_FAILED', $this->errorNum, $this->errorMsg), JLog::ERROR, 'databasequery');
throw new JDatabaseException($this->errorMsg, $this->errorNum);
}
}
return $this->cursor;
}
/**
* 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 11.1
* @throws JDatabaseException
*/
public function select($database)
{
if (!$database)
{
return false;
}
if (!mysqli_select_db($this->connection, $database) && !mysqli_select_db($this->connection_read, $database))
{
// Legacy error handling switch based on the JError::$legacy switch.
// @deprecated 12.1
if (JError::$legacy)
{
$this->errorNum = 3;
$this->errorMsg = JText::_('JLIB_DATABASE_ERROR_DATABASE_CONNECT');
return false;
}
else
{
throw new JDatabaseException(JText::_('JLIB_DATABASE_ERROR_DATABASE_CONNECT'));
}
}
return true;
}
/**
* Set the connection to use UTF-8 character encoding.
*
* @return boolean True on success.
*
* @since 11.1
*/
public function setUTF()
{
mysqli_set_charset($this->connection, 'utf8');
mysqli_set_charset($this->connection_read, 'utf8');
}
/**
* Method to fetch a row from the result set cursor as an array.
*
* @param mixed $cursor The optional result set cursor from which to fetch the row.
*
* @return mixed Either the next row from the result set or false if there are no more rows.
*
* @since 11.1
*/
protected function fetchArray($cursor = null)
{
return mysqli_fetch_row($cursor ? $cursor : $this->cursor);
}
/**
* Method to fetch a row from the result set cursor as an associative array.
*
* @param mixed $cursor The optional result set cursor from which to fetch the row.
*
* @return mixed Either the next row from the result set or false if there are no more rows.
*
* @since 11.1
*/
protected function fetchAssoc($cursor = null)
{
return mysqli_fetch_assoc($cursor ? $cursor : $this->cursor);
}
/**
* Method to fetch a row from the result set cursor as an object.
*
* @param mixed $cursor The optional result set cursor from which to fetch the row.
* @param string $class The class name to use for the returned row object.
*
* @return mixed Either the next row from the result set or false if there are no more rows.
*
* @since 11.1
*/
protected function fetchObject($cursor = null, $class = 'stdClass')
{
return mysqli_fetch_object($cursor ? $cursor : $this->cursor, $class);
}
/**
* Method to free up the memory used for the result set.
*
* @param mixed $cursor The optional result set cursor from which to fetch the row.
*
* @return void
*
* @since 11.1
*/
protected function freeResult($cursor = null)
{
mysqli_free_result($cursor ? $cursor : $this->cursor);
}
/**
* Execute a query batch.
*
* @param boolean $abortOnError Abort on error.
* @param boolean $transactionSafe Transaction safe queries.
*
* @return mixed A database resource if successful, false if not.
*
* @deprecated 12.1
* @since 11.1
*/
public function queryBatch($abortOnError = true, $transactionSafe = false)
{
// Deprecation warning.
JLog::add('JDatabaseMySQLi::queryBatch() is deprecated.', JLog::WARNING, 'deprecated');
$sql = $this->replacePrefix((string) $this->sql);
$this->errorNum = 0;
$this->errorMsg = '';
// If the batch is meant to be transaction safe then we need to wrap it in a transaction.
if ($transactionSafe)
{
$sql = 'START TRANSACTION;' . rtrim($sql, "; \t\r\n\0") . '; COMMIT;';
}
$queries = $this->splitSql($sql);
$error = 0;
foreach ($queries as $query)
{
$query = trim($query);
if ($query != '')
{
$this->cursor = mysqli_query($this->connection, $query);
if ($this->debug)
{
$this->count++;
$this->log[] = $query;
}
if (!$this->cursor)
{
$error = 1;
$this->errorNum .= mysqli_errno($this->connection) . ' ';
$this->errorMsg .= mysqli_error($this->connection) . " SQL=$query <br />";
if ($abortOnError)
{
return $this->cursor;
}
}
}
}
return $error ? false : true;
}
}
@siran
Copy link
Author

siran commented Apr 13, 2015

I get the error:

Duplicate entry 'h2rgkf6idru0r2lnpv5iqib3i1' for key 'PRIMARY' SQL=INSERT INTO `jos_session` (`session_id`, `client_id`, `time`) VALUES ('h2rgkf6idru0r2lnpv5iqib3i1', 0, '1428946167')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment