PageRenderTime 39ms CodeModel.GetById 1ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/endomorphosis/OLAAaction
PHP | 692 lines | 406 code | 52 blank | 234 comment | 76 complexity | 8864dfeaff5f1a274d29ddbcda754f5c MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id: mysql.php 16385 2010-04-23 10:44:15Z ian $
  4. * @package Joomla.Framework
  5. * @subpackage Database
  6. * @copyright Copyright (C) 2005 - 2010 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. // Take a local copy so that we don't modify the original query and cause issues later
  192. $sql = $this->_sql;
  193. if ($this->_limit > 0 || $this->_offset > 0) {
  194. $sql .= ' LIMIT ' . max($this->_offset, 0) . ', ' . max($this->_limit, 0);
  195. }
  196. if ($this->_debug) {
  197. $this->_ticker++;
  198. $this->_log[] = $sql;
  199. }
  200. $this->_errorNum = 0;
  201. $this->_errorMsg = '';
  202. $this->_cursor = mysql_query( $sql, $this->_resource );
  203. if (!$this->_cursor)
  204. {
  205. $this->_errorNum = mysql_errno( $this->_resource );
  206. $this->_errorMsg = mysql_error( $this->_resource )." SQL=$sql";
  207. if ($this->_debug) {
  208. JError::raiseError(500, 'JDatabaseMySQL::query: '.$this->_errorNum.' - '.$this->_errorMsg );
  209. }
  210. return false;
  211. }
  212. return $this->_cursor;
  213. }
  214. /**
  215. * Description
  216. *
  217. * @access public
  218. * @return int The number of affected rows in the previous operation
  219. * @since 1.0.5
  220. */
  221. function getAffectedRows()
  222. {
  223. return mysql_affected_rows( $this->_resource );
  224. }
  225. /**
  226. * Execute a batch query
  227. *
  228. * @access public
  229. * @return mixed A database resource if successful, FALSE if not.
  230. */
  231. function queryBatch( $abort_on_error=true, $p_transaction_safe = false)
  232. {
  233. $this->_errorNum = 0;
  234. $this->_errorMsg = '';
  235. if ($p_transaction_safe) {
  236. $this->_sql = rtrim($this->_sql, "; \t\r\n\0");
  237. $si = $this->getVersion();
  238. preg_match_all( "/(\d+)\.(\d+)\.(\d+)/i", $si, $m );
  239. if ($m[1] >= 4) {
  240. $this->_sql = 'START TRANSACTION;' . $this->_sql . '; COMMIT;';
  241. } else if ($m[2] >= 23 && $m[3] >= 19) {
  242. $this->_sql = 'BEGIN WORK;' . $this->_sql . '; COMMIT;';
  243. } else if ($m[2] >= 23 && $m[3] >= 17) {
  244. $this->_sql = 'BEGIN;' . $this->_sql . '; COMMIT;';
  245. }
  246. }
  247. $query_split = $this->splitSql($this->_sql);
  248. $error = 0;
  249. foreach ($query_split as $command_line) {
  250. $command_line = trim( $command_line );
  251. if ($command_line != '') {
  252. $this->_cursor = mysql_query( $command_line, $this->_resource );
  253. if ($this->_debug) {
  254. $this->_ticker++;
  255. $this->_log[] = $command_line;
  256. }
  257. if (!$this->_cursor) {
  258. $error = 1;
  259. $this->_errorNum .= mysql_errno( $this->_resource ) . ' ';
  260. $this->_errorMsg .= mysql_error( $this->_resource )." SQL=$command_line <br />";
  261. if ($abort_on_error) {
  262. return $this->_cursor;
  263. }
  264. }
  265. }
  266. }
  267. return $error ? false : true;
  268. }
  269. /**
  270. * Diagnostic function
  271. *
  272. * @access public
  273. * @return string
  274. */
  275. function explain()
  276. {
  277. $temp = $this->_sql;
  278. $this->_sql = "EXPLAIN $this->_sql";
  279. if (!($cur = $this->query())) {
  280. return null;
  281. }
  282. $first = true;
  283. $buffer = '<table id="explain-sql">';
  284. $buffer .= '<thead><tr><td colspan="99">'.$this->getQuery().'</td></tr>';
  285. while ($row = mysql_fetch_assoc( $cur )) {
  286. if ($first) {
  287. $buffer .= '<tr>';
  288. foreach ($row as $k=>$v) {
  289. $buffer .= '<th>'.$k.'</th>';
  290. }
  291. $buffer .= '</tr>';
  292. $first = false;
  293. }
  294. $buffer .= '</thead><tbody><tr>';
  295. foreach ($row as $k=>$v) {
  296. $buffer .= '<td>'.$v.'</td>';
  297. }
  298. $buffer .= '</tr>';
  299. }
  300. $buffer .= '</tbody></table>';
  301. mysql_free_result( $cur );
  302. $this->_sql = $temp;
  303. return $buffer;
  304. }
  305. /**
  306. * Description
  307. *
  308. * @access public
  309. * @return int The number of rows returned from the most recent query.
  310. */
  311. function getNumRows( $cur=null )
  312. {
  313. return mysql_num_rows( $cur ? $cur : $this->_cursor );
  314. }
  315. /**
  316. * This method loads the first field of the first row returned by the query.
  317. *
  318. * @access public
  319. * @return The value returned in the query or null if the query failed.
  320. */
  321. function loadResult()
  322. {
  323. if (!($cur = $this->query())) {
  324. return null;
  325. }
  326. $ret = null;
  327. if ($row = mysql_fetch_row( $cur )) {
  328. $ret = $row[0];
  329. }
  330. mysql_free_result( $cur );
  331. return $ret;
  332. }
  333. /**
  334. * Load an array of single field results into an array
  335. *
  336. * @access public
  337. */
  338. function loadResultArray($numinarray = 0)
  339. {
  340. if (!($cur = $this->query())) {
  341. return null;
  342. }
  343. $array = array();
  344. while ($row = mysql_fetch_row( $cur )) {
  345. $array[] = $row[$numinarray];
  346. }
  347. mysql_free_result( $cur );
  348. return $array;
  349. }
  350. /**
  351. * Fetch a result row as an associative array
  352. *
  353. * @access public
  354. * @return array
  355. */
  356. function loadAssoc()
  357. {
  358. if (!($cur = $this->query())) {
  359. return null;
  360. }
  361. $ret = null;
  362. if ($array = mysql_fetch_assoc( $cur )) {
  363. $ret = $array;
  364. }
  365. mysql_free_result( $cur );
  366. return $ret;
  367. }
  368. /**
  369. * Load a assoc list of database rows
  370. *
  371. * @access public
  372. * @param string The field name of a primary key
  373. * @return array If <var>key</var> is empty as sequential list of returned records.
  374. */
  375. function loadAssocList( $key='' )
  376. {
  377. if (!($cur = $this->query())) {
  378. return null;
  379. }
  380. $array = array();
  381. while ($row = mysql_fetch_assoc( $cur )) {
  382. if ($key) {
  383. $array[$row[$key]] = $row;
  384. } else {
  385. $array[] = $row;
  386. }
  387. }
  388. mysql_free_result( $cur );
  389. return $array;
  390. }
  391. /**
  392. * This global function loads the first row of a query into an object
  393. *
  394. * @access public
  395. * @return object
  396. */
  397. function loadObject( )
  398. {
  399. if (!($cur = $this->query())) {
  400. return null;
  401. }
  402. $ret = null;
  403. if ($object = mysql_fetch_object( $cur )) {
  404. $ret = $object;
  405. }
  406. mysql_free_result( $cur );
  407. return $ret;
  408. }
  409. /**
  410. * Load a list of database objects
  411. *
  412. * If <var>key</var> is not empty then the returned array is indexed by the value
  413. * the database key. Returns <var>null</var> if the query fails.
  414. *
  415. * @access public
  416. * @param string The field name of a primary key
  417. * @return array If <var>key</var> is empty as sequential list of returned records.
  418. */
  419. function loadObjectList( $key='' )
  420. {
  421. if (!($cur = $this->query())) {
  422. return null;
  423. }
  424. $array = array();
  425. while ($row = mysql_fetch_object( $cur )) {
  426. if ($key) {
  427. $array[$row->$key] = $row;
  428. } else {
  429. $array[] = $row;
  430. }
  431. }
  432. mysql_free_result( $cur );
  433. return $array;
  434. }
  435. /**
  436. * Description
  437. *
  438. * @access public
  439. * @return The first row of the query.
  440. */
  441. function loadRow()
  442. {
  443. if (!($cur = $this->query())) {
  444. return null;
  445. }
  446. $ret = null;
  447. if ($row = mysql_fetch_row( $cur )) {
  448. $ret = $row;
  449. }
  450. mysql_free_result( $cur );
  451. return $ret;
  452. }
  453. /**
  454. * Load a list of database rows (numeric column indexing)
  455. *
  456. * @access public
  457. * @param string The field name of a primary key
  458. * @return array If <var>key</var> is empty as sequential list of returned records.
  459. * If <var>key</var> is not empty then the returned array is indexed by the value
  460. * the database key. Returns <var>null</var> if the query fails.
  461. */
  462. function loadRowList( $key=null )
  463. {
  464. if (!($cur = $this->query())) {
  465. return null;
  466. }
  467. $array = array();
  468. while ($row = mysql_fetch_row( $cur )) {
  469. if ($key !== null) {
  470. $array[$row[$key]] = $row;
  471. } else {
  472. $array[] = $row;
  473. }
  474. }
  475. mysql_free_result( $cur );
  476. return $array;
  477. }
  478. /**
  479. * Inserts a row into a table based on an objects properties
  480. *
  481. * @access public
  482. * @param string The name of the table
  483. * @param object An object whose properties match table fields
  484. * @param string The name of the primary key. If provided the object property is updated.
  485. */
  486. function insertObject( $table, &$object, $keyName = NULL )
  487. {
  488. $fmtsql = 'INSERT INTO '.$this->nameQuote($table).' ( %s ) VALUES ( %s ) ';
  489. $fields = array();
  490. foreach (get_object_vars( $object ) as $k => $v) {
  491. if (is_array($v) or is_object($v) or $v === NULL) {
  492. continue;
  493. }
  494. if ($k[0] == '_') { // internal field
  495. continue;
  496. }
  497. $fields[] = $this->nameQuote( $k );
  498. $values[] = $this->isQuoted( $k ) ? $this->Quote( $v ) : (int) $v;
  499. }
  500. $this->setQuery( sprintf( $fmtsql, implode( ",", $fields ) , implode( ",", $values ) ) );
  501. if (!$this->query()) {
  502. return false;
  503. }
  504. $id = $this->insertid();
  505. if ($keyName && $id) {
  506. $object->$keyName = $id;
  507. }
  508. return true;
  509. }
  510. /**
  511. * Description
  512. *
  513. * @access public
  514. * @param [type] $updateNulls
  515. */
  516. function updateObject( $table, &$object, $keyName, $updateNulls=true )
  517. {
  518. $fmtsql = 'UPDATE '.$this->nameQuote($table).' SET %s WHERE %s';
  519. $tmp = array();
  520. foreach (get_object_vars( $object ) as $k => $v)
  521. {
  522. if( is_array($v) or is_object($v) or $k[0] == '_' ) { // internal or NA field
  523. continue;
  524. }
  525. if( $k == $keyName ) { // PK not to be updated
  526. $where = $keyName . '=' . $this->Quote( $v );
  527. continue;
  528. }
  529. if ($v === null)
  530. {
  531. if ($updateNulls) {
  532. $val = 'NULL';
  533. } else {
  534. continue;
  535. }
  536. } else {
  537. $val = $this->isQuoted( $k ) ? $this->Quote( $v ) : (int) $v;
  538. }
  539. $tmp[] = $this->nameQuote( $k ) . '=' . $val;
  540. }
  541. $this->setQuery( sprintf( $fmtsql, implode( ",", $tmp ) , $where ) );
  542. return $this->query();
  543. }
  544. /**
  545. * Description
  546. *
  547. * @access public
  548. */
  549. function insertid()
  550. {
  551. return mysql_insert_id( $this->_resource );
  552. }
  553. /**
  554. * Description
  555. *
  556. * @access public
  557. */
  558. function getVersion()
  559. {
  560. return mysql_get_server_info( $this->_resource );
  561. }
  562. /**
  563. * Assumes database collation in use by sampling one text field in one table
  564. *
  565. * @access public
  566. * @return string Collation in use
  567. */
  568. function getCollation ()
  569. {
  570. if ( $this->hasUTF() ) {
  571. $this->setQuery( 'SHOW FULL COLUMNS FROM #__content' );
  572. $array = $this->loadAssocList();
  573. return $array['4']['Collation'];
  574. } else {
  575. return "N/A (mySQL < 4.1.2)";
  576. }
  577. }
  578. /**
  579. * Description
  580. *
  581. * @access public
  582. * @return array A list of all the tables in the database
  583. */
  584. function getTableList()
  585. {
  586. $this->setQuery( 'SHOW TABLES' );
  587. return $this->loadResultArray();
  588. }
  589. /**
  590. * Shows the CREATE TABLE statement that creates the given tables
  591. *
  592. * @access public
  593. * @param array|string A table name or a list of table names
  594. * @return array A list the create SQL for the tables
  595. */
  596. function getTableCreate( $tables )
  597. {
  598. settype($tables, 'array'); //force to array
  599. $result = array();
  600. foreach ($tables as $tblval) {
  601. $this->setQuery( 'SHOW CREATE table ' . $this->getEscaped( $tblval ) );
  602. $rows = $this->loadRowList();
  603. foreach ($rows as $row) {
  604. $result[$tblval] = $row[1];
  605. }
  606. }
  607. return $result;
  608. }
  609. /**
  610. * Retrieves information about the given tables
  611. *
  612. * @access public
  613. * @param array|string A table name or a list of table names
  614. * @param boolean Only return field types, default true
  615. * @return array An array of fields by table
  616. */
  617. function getTableFields( $tables, $typeonly = true )
  618. {
  619. settype($tables, 'array'); //force to array
  620. $result = array();
  621. foreach ($tables as $tblval)
  622. {
  623. $this->setQuery( 'SHOW FIELDS FROM ' . $tblval );
  624. $fields = $this->loadObjectList();
  625. if($typeonly)
  626. {
  627. foreach ($fields as $field) {
  628. $result[$tblval][$field->Field] = preg_replace("/[(0-9)]/",'', $field->Type );
  629. }
  630. }
  631. else
  632. {
  633. foreach ($fields as $field) {
  634. $result[$tblval][$field->Field] = $field;
  635. }
  636. }
  637. }
  638. return $result;
  639. }
  640. }