PageRenderTime 24ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/database/database/mysqli.php

https://gitlab.com/endomorphosis/greenrenaissancejoomla
PHP | 702 lines | 409 code | 53 blank | 240 comment | 78 complexity | 92490726b47e78e6a3cfd23b49abc705 MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id: mysqli.php 9978 2008-02-01 17:23:39Z ircmaxell $
  4. * @package Joomla.Framework
  5. * @subpackage Database
  6. * @copyright Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
  7. * @license GNU/GPL, see LICENSE.php
  8. * Joomla! is free software. This version may have been modified pursuant
  9. * to the GNU General Public License, and as distributed it includes or
  10. * is derivative of works licensed under the GNU General Public License or
  11. * other free or open source software licenses.
  12. * See COPYRIGHT.php for copyright notices and details.
  13. */
  14. // Check to ensure this file is within the rest of the framework
  15. defined('JPATH_BASE') or die();
  16. /**
  17. * MySQLi database driver
  18. *
  19. * @package Joomla.Framework
  20. * @subpackage Database
  21. * @since 1.0
  22. */
  23. class JDatabaseMySQLi extends JDatabase
  24. {
  25. /**
  26. * The database driver name
  27. *
  28. * @var string
  29. */
  30. var $name = 'mysqli';
  31. /**
  32. * The null/zero date string
  33. *
  34. * @var string
  35. */
  36. var $_nullDate = '0000-00-00 00:00:00';
  37. /**
  38. * Quote for named objects
  39. *
  40. * @var string
  41. */
  42. var $_nameQuote = '`';
  43. /**
  44. * Database object constructor
  45. *
  46. * @access public
  47. * @param array List of options used to configure the connection
  48. * @since 1.5
  49. * @see JDatabase
  50. */
  51. function __construct( $options )
  52. {
  53. $host = array_key_exists('host', $options) ? $options['host'] : 'localhost';
  54. $user = array_key_exists('user', $options) ? $options['user'] : '';
  55. $password = array_key_exists('password',$options) ? $options['password'] : '';
  56. $database = array_key_exists('database',$options) ? $options['database'] : '';
  57. $prefix = array_key_exists('prefix', $options) ? $options['prefix'] : 'jos_';
  58. $select = array_key_exists('select', $options) ? $options['select'] : true;
  59. // Unlike mysql_connect(), mysqli_connect() takes the port and socket
  60. // as separate arguments. Therefore, we have to extract them from the
  61. // host string.
  62. $port = NULL;
  63. $socket = NULL;
  64. $targetSlot = substr( strstr( $host, ":" ), 1 );
  65. if (!empty( $targetSlot )) {
  66. // Get the port number or socket name
  67. if (is_numeric( $targetSlot ))
  68. $port = $targetSlot;
  69. else
  70. $socket = $targetSlot;
  71. // Extract the host name only
  72. $host = substr( $host, 0, strlen( $host ) - (strlen( $targetSlot ) + 1) );
  73. // This will take care of the following notation: ":3306"
  74. if($host == '')
  75. $host = 'localhost';
  76. }
  77. // perform a number of fatality checks, then return gracefully
  78. if (!function_exists( 'mysqli_connect' )) {
  79. $this->_errorNum = 1;
  80. $this->_errorMsg = 'The MySQL adapter "mysqli" is not available.';
  81. return;
  82. }
  83. // connect to the server
  84. if (!($this->_resource = @mysqli_connect($host, $user, $password, NULL, $port, $socket))) {
  85. $this->_errorNum = 2;
  86. $this->_errorMsg = 'Could not connect to MySQL';
  87. return;
  88. }
  89. // finalize initialization
  90. parent::__construct($options);
  91. // select the database
  92. if ( $select ) {
  93. $this->select($database);
  94. }
  95. }
  96. /**
  97. * Database object destructor
  98. *
  99. * @return boolean
  100. * @since 1.5
  101. */
  102. function __destruct()
  103. {
  104. $return = false;
  105. if (is_resource($this->_resource)) {
  106. $return = mysqli_close($this->_resource);
  107. }
  108. return $return;
  109. }
  110. /**
  111. * Test to see if the MySQLi connector is available
  112. *
  113. * @static
  114. * @access public
  115. * @return boolean True on success, false otherwise.
  116. */
  117. function test()
  118. {
  119. return (function_exists( 'mysqli_connect' ));
  120. }
  121. /**
  122. * Determines if the connection to the server is active.
  123. *
  124. * @access public
  125. * @return boolean
  126. * @since 1.5
  127. */
  128. function connected()
  129. {
  130. return $this->_resource->ping();
  131. }
  132. /**
  133. * Select a database for use
  134. *
  135. * @access public
  136. * @param string $database
  137. * @return boolean True if the database has been successfully selected
  138. * @since 1.5
  139. */
  140. function select($database)
  141. {
  142. if ( ! $database )
  143. {
  144. return false;
  145. }
  146. if ( !mysqli_select_db($this->_resource, $database)) {
  147. $this->_errorNum = 3;
  148. $this->_errorMsg = 'Could not connect to database';
  149. return false;
  150. }
  151. // if running mysql 5, set sql-mode to mysql40 - thereby circumventing strict mode problems
  152. if ( strpos( $this->getVersion(), '5' ) === 0 ) {
  153. $this->setQuery( "SET sql_mode = 'MYSQL40'" );
  154. $this->query();
  155. }
  156. return true;
  157. }
  158. /**
  159. * Determines UTF support
  160. *
  161. * @access public
  162. * @return boolean True - UTF is supported
  163. */
  164. function hasUTF()
  165. {
  166. $verParts = explode( '.', $this->getVersion() );
  167. return ($verParts[0] == 5 || ($verParts[0] == 4 && $verParts[1] == 1 && (int)$verParts[2] >= 2));
  168. }
  169. /**
  170. * Custom settings for UTF support
  171. *
  172. * @access public
  173. */
  174. function setUTF()
  175. {
  176. mysqli_query( $this->_resource, "SET NAMES 'utf8'" );
  177. }
  178. /**
  179. * Get a database escaped string
  180. *
  181. * @param string The string to be escaped
  182. * @param boolean Optional parameter to provide extra escaping
  183. * @return string
  184. * @access public
  185. * @abstract
  186. */
  187. function getEscaped( $text, $extra = false )
  188. {
  189. $result = mysqli_real_escape_string( $this->_resource, $text );
  190. if ($extra) {
  191. $result = addcslashes( $result, '%_' );
  192. }
  193. return $result;
  194. }
  195. /**
  196. * Execute the query
  197. *
  198. * @access public
  199. * @return mixed A database resource if successful, FALSE if not.
  200. */
  201. function query()
  202. {
  203. if (!is_object($this->_resource)) {
  204. return false;
  205. }
  206. if ($this->_limit > 0 || $this->_offset > 0) {
  207. $this->_sql .= ' LIMIT '.$this->_offset.', '.$this->_limit;
  208. }
  209. if ($this->_debug) {
  210. $this->_ticker++;
  211. $this->_log[] = $this->_sql;
  212. }
  213. $this->_errorNum = 0;
  214. $this->_errorMsg = '';
  215. $this->_cursor = mysqli_query( $this->_resource, $this->_sql );
  216. if (!$this->_cursor)
  217. {
  218. $this->_errorNum = mysqli_errno( $this->_resource );
  219. $this->_errorMsg = mysqli_error( $this->_resource )." SQL=$this->_sql";
  220. if ($this->_debug) {
  221. JError::raiseError(500, 'JDatabaseMySQL::query: '.$this->_errorNum.' - '.$this->_errorMsg );
  222. }
  223. return false;
  224. }
  225. return $this->_cursor;
  226. }
  227. /**
  228. * Description
  229. *
  230. * @access public
  231. * @return int The number of affected rows in the previous operation
  232. * @since 1.0.5
  233. */
  234. function getAffectedRows()
  235. {
  236. return mysqli_affected_rows( $this->_resource );
  237. }
  238. /**
  239. * Execute a batch query
  240. *
  241. * @access public
  242. * @return mixed A database resource if successful, FALSE if not.
  243. */
  244. function queryBatch( $abort_on_error=true, $p_transaction_safe = false)
  245. {
  246. $this->_errorNum = 0;
  247. $this->_errorMsg = '';
  248. if ($p_transaction_safe) {
  249. $si = $this->getVersion();
  250. preg_match_all( "/(\d+)\.(\d+)\.(\d+)/i", $si, $m );
  251. if ($m[1] >= 4) {
  252. $this->_sql = 'START TRANSACTION;' . $this->_sql . '; COMMIT;';
  253. } else if ($m[2] >= 23 && $m[3] >= 19) {
  254. $this->_sql = 'BEGIN WORK;' . $this->_sql . '; COMMIT;';
  255. } else if ($m[2] >= 23 && $m[3] >= 17) {
  256. $this->_sql = 'BEGIN;' . $this->_sql . '; COMMIT;';
  257. }
  258. }
  259. $query_split = $this->splitSql($this->_sql);
  260. $error = 0;
  261. foreach ($query_split as $command_line) {
  262. $command_line = trim( $command_line );
  263. if ($command_line != '') {
  264. $this->_cursor = mysqli_query( $this->_resource, $command_line );
  265. if (!$this->_cursor) {
  266. $error = 1;
  267. $this->_errorNum .= mysqli_errno( $this->_resource ) . ' ';
  268. $this->_errorMsg .= mysqli_error( $this->_resource )." SQL=$command_line <br />";
  269. if ($abort_on_error) {
  270. return $this->_cursor;
  271. }
  272. }
  273. }
  274. }
  275. return $error ? false : true;
  276. }
  277. /**
  278. * Diagnostic function
  279. *
  280. * @access public
  281. * @return string
  282. */
  283. function explain()
  284. {
  285. $temp = $this->_sql;
  286. $this->_sql = "EXPLAIN $this->_sql";
  287. if (!($cur = $this->query())) {
  288. return null;
  289. }
  290. $first = true;
  291. $buffer = '<table id="explain-sql">';
  292. $buffer .= '<thead><tr><td colspan="99">'.$this->getQuery().'</td></tr>';
  293. while ($row = mysqli_fetch_assoc( $cur )) {
  294. if ($first) {
  295. $buffer .= '<tr>';
  296. foreach ($row as $k=>$v) {
  297. $buffer .= '<th>'.$k.'</th>';
  298. }
  299. $buffer .= '</tr>';
  300. $first = false;
  301. }
  302. $buffer .= '</thead><tbody><tr>';
  303. foreach ($row as $k=>$v) {
  304. $buffer .= '<td>'.$v.'</td>';
  305. }
  306. $buffer .= '</tr>';
  307. }
  308. $buffer .= '</tbody></table>';
  309. mysqli_free_result( $cur );
  310. $this->_sql = $temp;
  311. return $buffer;
  312. }
  313. /**
  314. * Description
  315. *
  316. * @access public
  317. * @return int The number of rows returned from the most recent query.
  318. */
  319. function getNumRows( $cur=null )
  320. {
  321. return mysqli_num_rows( $cur ? $cur : $this->_cursor );
  322. }
  323. /**
  324. * This method loads the first field of the first row returned by the query.
  325. *
  326. * @access public
  327. * @return The value returned in the query or null if the query failed.
  328. */
  329. function loadResult()
  330. {
  331. if (!($cur = $this->query())) {
  332. return null;
  333. }
  334. $ret = null;
  335. if ($row = mysqli_fetch_row( $cur )) {
  336. $ret = $row[0];
  337. }
  338. mysqli_free_result( $cur );
  339. return $ret;
  340. }
  341. /**
  342. * Load an array of single field results into an array
  343. *
  344. * @access public
  345. */
  346. function loadResultArray($numinarray = 0)
  347. {
  348. if (!($cur = $this->query())) {
  349. return null;
  350. }
  351. $array = array();
  352. while ($row = mysqli_fetch_row( $cur )) {
  353. $array[] = $row[$numinarray];
  354. }
  355. mysqli_free_result( $cur );
  356. return $array;
  357. }
  358. /**
  359. * Fetch a result row as an associative array
  360. *
  361. * @access public
  362. * @return array
  363. */
  364. function loadAssoc()
  365. {
  366. if (!($cur = $this->query())) {
  367. return null;
  368. }
  369. $ret = null;
  370. if ($array = mysqli_fetch_assoc( $cur )) {
  371. $ret = $array;
  372. }
  373. mysqli_free_result( $cur );
  374. return $ret;
  375. }
  376. /**
  377. * Load a assoc list of database rows
  378. *
  379. * @access public
  380. * @param string The field name of a primary key
  381. * @return array If <var>key</var> is empty as sequential list of returned records.
  382. */
  383. function loadAssocList( $key='' )
  384. {
  385. if (!($cur = $this->query())) {
  386. return null;
  387. }
  388. $array = array();
  389. while ($row = mysqli_fetch_assoc( $cur )) {
  390. if ($key) {
  391. $array[$row[$key]] = $row;
  392. } else {
  393. $array[] = $row;
  394. }
  395. }
  396. mysqli_free_result( $cur );
  397. return $array;
  398. }
  399. /**
  400. * This global function loads the first row of a query into an object
  401. *
  402. * @access public
  403. * @return object
  404. */
  405. function loadObject( )
  406. {
  407. if (!($cur = $this->query())) {
  408. return null;
  409. }
  410. $ret = null;
  411. if ($object = mysqli_fetch_object( $cur )) {
  412. $ret = $object;
  413. }
  414. mysqli_free_result( $cur );
  415. return $ret;
  416. }
  417. /**
  418. * Load a list of database objects
  419. *
  420. * If <var>key</var> is not empty then the returned array is indexed by the value
  421. * the database key. Returns <var>null</var> if the query fails.
  422. *
  423. * @access public
  424. * @param string The field name of a primary key
  425. * @return array If <var>key</var> is empty as sequential list of returned records.
  426. */
  427. function loadObjectList( $key='' )
  428. {
  429. if (!($cur = $this->query())) {
  430. return null;
  431. }
  432. $array = array();
  433. while ($row = mysqli_fetch_object( $cur )) {
  434. if ($key) {
  435. $array[$row->$key] = $row;
  436. } else {
  437. $array[] = $row;
  438. }
  439. }
  440. mysqli_free_result( $cur );
  441. return $array;
  442. }
  443. /**
  444. * Description
  445. *
  446. * @access public
  447. * @return The first row of the query.
  448. */
  449. function loadRow()
  450. {
  451. if (!($cur = $this->query())) {
  452. return null;
  453. }
  454. $ret = null;
  455. if ($row = mysqli_fetch_row( $cur )) {
  456. $ret = $row;
  457. }
  458. mysqli_free_result( $cur );
  459. return $ret;
  460. }
  461. /**
  462. * Load a list of database rows (numeric column indexing)
  463. *
  464. * If <var>key</var> is not empty then the returned array is indexed by the value
  465. * the database key. Returns <var>null</var> if the query fails.
  466. *
  467. * @access public
  468. * @param string The field name of a primary key
  469. * @return array If <var>key</var> is empty as sequential list of returned records.
  470. */
  471. function loadRowList( $key=null )
  472. {
  473. if (!($cur = $this->query())) {
  474. return null;
  475. }
  476. $array = array();
  477. while ($row = mysqli_fetch_row( $cur )) {
  478. if ($key !== null) {
  479. $array[$row[$key]] = $row;
  480. } else {
  481. $array[] = $row;
  482. }
  483. }
  484. mysqli_free_result( $cur );
  485. return $array;
  486. }
  487. /**
  488. * Inserts a row into a table based on an objects properties
  489. *
  490. * @access public
  491. * @param string The name of the table
  492. * @param object An object whose properties match table fields
  493. * @param string The name of the primary key. If provided the object property is updated.
  494. */
  495. function insertObject( $table, &$object, $keyName = NULL )
  496. {
  497. $fmtsql = "INSERT INTO $table ( %s ) VALUES ( %s ) ";
  498. $fields = array();
  499. foreach (get_object_vars( $object ) as $k => $v) {
  500. if (is_array($v) or is_object($v) or $v === NULL) {
  501. continue;
  502. }
  503. if ($k[0] == '_') { // internal field
  504. continue;
  505. }
  506. $fields[] = $this->nameQuote( $k );
  507. $values[] = $this->isQuoted( $k ) ? $this->Quote( $v ) : (int) $v;
  508. }
  509. $this->setQuery( sprintf( $fmtsql, implode( ",", $fields ) , implode( ",", $values ) ) );
  510. if (!$this->query()) {
  511. return false;
  512. }
  513. $id = $this->insertid();
  514. if ($keyName && $id) {
  515. $object->$keyName = $id;
  516. }
  517. return true;
  518. }
  519. /**
  520. * Description
  521. *
  522. * @access public
  523. * @param [type] $updateNulls
  524. */
  525. function updateObject( $table, &$object, $keyName, $updateNulls=true )
  526. {
  527. $fmtsql = "UPDATE $table SET %s WHERE %s";
  528. $tmp = array();
  529. foreach (get_object_vars( $object ) as $k => $v) {
  530. if( is_array($v) or is_object($v) or $k[0] == '_' ) { // internal or NA field
  531. continue;
  532. }
  533. if( $k == $keyName ) { // PK not to be updated
  534. $where = $keyName . '=' . $this->Quote( $v );
  535. continue;
  536. }
  537. if ($v === null)
  538. {
  539. if ($updateNulls) {
  540. $val = 'NULL';
  541. } else {
  542. continue;
  543. }
  544. } else {
  545. $val = $this->isQuoted( $k ) ? $this->Quote( $v ) : (int) $v;
  546. }
  547. $tmp[] = $this->nameQuote( $k ) . '=' . $val;
  548. }
  549. $this->setQuery( sprintf( $fmtsql, implode( ",", $tmp ) , $where ) );
  550. return $this->query();
  551. }
  552. /**
  553. * Description
  554. *
  555. * @access public
  556. */
  557. function insertid()
  558. {
  559. return mysqli_insert_id( $this->_resource );
  560. }
  561. /**
  562. * Description
  563. *
  564. * @access public
  565. */
  566. function getVersion()
  567. {
  568. return mysqli_get_server_info( $this->_resource );
  569. }
  570. /**
  571. * Assumes database collation in use by sampling one text field in one table
  572. *
  573. * @access public
  574. * @return string Collation in use
  575. */
  576. function getCollation ()
  577. {
  578. if ( $this->hasUTF() ) {
  579. $this->setQuery( 'SHOW FULL COLUMNS FROM #__content' );
  580. $array = $this->loadAssocList();
  581. return $array['4']['Collation'];
  582. } else {
  583. return "N/A (mySQL < 4.1.2)";
  584. }
  585. }
  586. /**
  587. * Description
  588. *
  589. * @access public
  590. * @return array A list of all the tables in the database
  591. */
  592. function getTableList()
  593. {
  594. $this->setQuery( 'SHOW TABLES' );
  595. return $this->loadResultArray();
  596. }
  597. /**
  598. * Shows the CREATE TABLE statement that creates the given tables
  599. *
  600. * @access public
  601. * @param array|string A table name or a list of table names
  602. * @return array A list the create SQL for the tables
  603. */
  604. function getTableCreate( $tables )
  605. {
  606. settype($tables, 'array'); //force to array
  607. $result = array();
  608. foreach ($tables as $tblval)
  609. {
  610. $this->setQuery( 'SHOW CREATE table ' . $this->getEscaped( $tblval ) );
  611. $rows = $this->loadRowList();
  612. foreach ($rows as $row) {
  613. $result[$tblval] = $row[1];
  614. }
  615. }
  616. return $result;
  617. }
  618. /**
  619. * Retrieves information about the given tables
  620. *
  621. * @access public
  622. * @param array|string A table name or a list of table names
  623. * @param boolean Only return field types, default true
  624. * @return array An array of fields by table
  625. */
  626. function getTableFields( $tables, $typeonly = true )
  627. {
  628. settype($tables, 'array'); //force to array
  629. $result = array();
  630. foreach ($tables as $tblval)
  631. {
  632. $this->setQuery( 'SHOW FIELDS FROM ' . $tblval );
  633. $fields = $this->loadObjectList();
  634. if($typeonly)
  635. {
  636. foreach ($fields as $field) {
  637. $result[$tblval][$field->Field] = preg_replace("/[(0-9)]/",'', $field->Type );
  638. }
  639. }
  640. else
  641. {
  642. foreach ($fields as $field) {
  643. $result[$tblval][$field->Field] = $field;
  644. }
  645. }
  646. }
  647. return $result;
  648. }
  649. }