PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/database/database/mysql.php

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