PageRenderTime 787ms CodeModel.GetById 16ms RepoModel.GetById 2ms app.codeStats 0ms

/lib/yadal/class.PostgreSQL.php

https://github.com/reshadf/Library
PHP | 670 lines | 419 code | 58 blank | 193 comment | 28 complexity | d9ddd2b23fc57902fe609e9f65a4ac32 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * Yadal interface for the PostgreSQL database type
  4. *
  5. * @package Yadal
  6. */
  7. /**
  8. * class PostgreSQL
  9. *
  10. * Yadal - Yet Another Database Abstraction Layer
  11. * PostgreSQL class
  12. *
  13. * @author Teye Heimans
  14. * @package Yadal
  15. */
  16. class PostgreSQL extends Yadal
  17. {
  18. /**
  19. * PostgreSQL::PostgreSQL()
  20. *
  21. * Constructor
  22. *
  23. * @param string $db: The database to use to
  24. * @author Teye Heimans
  25. */
  26. function PostgreSQL( $db )
  27. {
  28. $this->Yadal( $db );
  29. $this->_nameQuote = array('"', '"');
  30. $this->_quoteNumbers = true;
  31. }
  32. /**
  33. * PostgreSQL::connect()
  34. *
  35. * Public: Make a connection with the database and
  36. * select the database.
  37. *
  38. * @param string host: the host to connect to
  39. * @param string username: the username which should be used to login
  40. * @param string password: the password which should be used to login
  41. * @return resource: The connection resource or false on failure
  42. * @access public
  43. * @author Teye Heimans
  44. */
  45. function connect( $host = '', $username = '', $password = '' )
  46. {
  47. // build connection string based on internal settings.
  48. $connStr = '';
  49. if(!empty($host)) $connStr .= "host=" . $host. " ";
  50. if(!empty($this->_db)) $connStr .= "dbname=" . $this->_db . " ";
  51. if(!empty($username)) $connStr .= "user=" . $username . " ";
  52. if(!empty($password)) $connStr .= "password=" . $password . " ";
  53. $connStr = trim($connStr);
  54. // make a connection
  55. $connID = pg_connect($connStr);
  56. // connected?
  57. if ( $connID )
  58. {
  59. $this->_conn = $connID;
  60. $this->query("set datestyle='ISO'");
  61. $this->query("set client_encoding = latin1;");
  62. $this->_isConnected = true;
  63. // return the connection resource
  64. return $this->_conn;
  65. }
  66. else
  67. {
  68. // connection failed...
  69. return false;
  70. }
  71. }
  72. /**
  73. * PostgreSQL::close()
  74. *
  75. * Close the connection
  76. *
  77. * @return bool
  78. * @access public
  79. * @author Teye Heimans
  80. */
  81. function close()
  82. {
  83. if( $this->_isConnected )
  84. {
  85. $this->_isConnected = false;
  86. return pg_close( $this->_conn );
  87. }
  88. }
  89. /**
  90. * PostgreSQL::query()
  91. *
  92. * Execute a query
  93. *
  94. * @param string $query: The query which should be executed
  95. * @return resource
  96. * @access public
  97. * @author Teye Heimans
  98. */
  99. function query( $query )
  100. {
  101. $this->_lastQuery = $query;
  102. return pg_query( $this->_conn, $query );
  103. }
  104. /**
  105. * PostgreSQL::getInsertId()
  106. *
  107. * Get the id of the last inserted record
  108. *
  109. * @param string $table: de tabel waarvan de laatste id van terug gegeven moet worden
  110. * @return int
  111. * @access public
  112. * @author Teye Heimans
  113. */
  114. function getInsertId( $table )
  115. {
  116. $k = $this->getPrKeys( $table );
  117. // select the last insert id for that table
  118. $sql = $this->query("
  119. SELECT last_value
  120. FROM ".$this->quote($table."_".$k[0]."_seq")
  121. );
  122. // query failed?
  123. if (!$sql)
  124. {
  125. trigger_error(
  126. "Could not retrieve the last inserted id for the table '".$table."'.\n".
  127. "Query: ".$this->getLastQuery()."\n".
  128. "Error: ".$this->getError(),
  129. E_USER_WARNING
  130. );
  131. return false;
  132. }
  133. // get the last inserted id
  134. if( $this->recordCount( $sql ) == 1 )
  135. {
  136. $row = @pg_fetch_row( $sql, 0 );
  137. pg_freeresult( $sql );
  138. return $row[0];
  139. }
  140. else
  141. {
  142. pg_freeresult( $sql );
  143. trigger_error(
  144. "Could not retrieve the last inserted id for the table '".$table."'.\n".
  145. "Query: ".$this->getLastQuery()."\n".
  146. "Error: ".$this->getError(),
  147. E_USER_WARNING
  148. );
  149. return false;
  150. }
  151. }
  152. /**
  153. * PostgreSQL::getError()
  154. *
  155. * Return the last error
  156. *
  157. * @param resource $sql: When you give a sql resource as parameter the last error of that result will be returned
  158. * @return string
  159. * @access public
  160. * @author Teye Heimans
  161. */
  162. function getError( $sql = null)
  163. {
  164. return !is_null($sql) ? pg_result_error($this->_sql) : pg_last_error();
  165. }
  166. /**
  167. * PostgreSQL::result()
  168. *
  169. * Return a specific result of a sql resource
  170. *
  171. * @param resource $result: The sql result where you want to get a result from
  172. * @param int $row: The row where you want a result from
  173. * @param string $field: The field which result you want
  174. * @return string
  175. * @access public
  176. * @author Teye Heimans
  177. */
  178. function result( $result, $row = 0, $field = null )
  179. {
  180. return pg_result( $result, $row, $field );
  181. }
  182. /**
  183. * PostgreSQL::recordCount()
  184. *
  185. * Return the number of records found by the query
  186. *
  187. * @return int
  188. * @access public
  189. * @author Teye Heimans
  190. */
  191. function recordCount( $sql)
  192. {
  193. return pg_numrows( $sql );
  194. }
  195. /**
  196. * PostgreSQL::getRecord()
  197. *
  198. * Fetch a record in assoc mode and return it
  199. *
  200. * @param resource $sql: The sql resource where we should get a record from
  201. * @return assoc array or false when there are no records left
  202. * @access public
  203. * @author Teye Heimans
  204. */
  205. function getRecord( $sql )
  206. {
  207. return pg_fetch_assoc( $sql );
  208. }
  209. /**
  210. * PostgreSQL::getFieldNames()
  211. *
  212. * Return the field names of the table
  213. *
  214. * @param string $table: The table to get the field names from
  215. * @return array
  216. * @access public
  217. * @author Teye Heimans
  218. */
  219. function getFieldNames( $table )
  220. {
  221. $t = strtolower($table);
  222. // return the data from the cache if it exists
  223. if( isset( $this->_cache['fields'][$t] ) )
  224. {
  225. return $this->_cache['fields'][$t];
  226. }
  227. $result = array();
  228. $sql = $this->query("
  229. SELECT
  230. a.attname AS name
  231. FROM
  232. pg_class c,
  233. pg_attribute
  234. a,pg_type t
  235. WHERE
  236. relkind = 'r' AND
  237. c.relname='".$table."' AND
  238. a.attnum > 0 AND
  239. a.atttypid = t.oid AND
  240. a.attrelid = c.oid
  241. ORDER BY a.attnum"
  242. );
  243. // query failed ?
  244. if( ! $sql )
  245. {
  246. trigger_error(
  247. "Could not fetch fieldnames of the table '".$table."'.\n".
  248. "Query: ".$this->getLastQuery()."\n".
  249. "Error: ".$this->getError(),
  250. E_USER_WARNING
  251. );
  252. return false;
  253. }
  254. while( $row = $this->getRecord($sql) )
  255. {
  256. $result[] = $row['name'];
  257. }
  258. // save the result in the cache
  259. $this->_cache['fields'][$t] = $result;
  260. return $result;
  261. }
  262. /**
  263. * PostgreSQL::getTables()
  264. *
  265. * Return the tables from the database
  266. *
  267. * @return array
  268. * @access public
  269. * @author Teye Heimans
  270. */
  271. function getTables()
  272. {
  273. // return the data from the cache if it exists
  274. if( isset( $this->_cache['tables'] ) )
  275. {
  276. return $this->_cache['tables'];
  277. }
  278. // selecteer de tabellen
  279. $sql = $this->query("
  280. SELECT tablename
  281. FROM pg_tables
  282. WHERE
  283. tablename NOT LIKE 'pg_%' AND
  284. tablename NOT LIKE 'sql_%'
  285. ORDER BY 1"
  286. );
  287. // query failed ?
  288. if( !$sql )
  289. {
  290. trigger_error(
  291. "Could not retrieve the tables from the database!\n".
  292. "Query: ".$this->getLastQuery()."\n".
  293. "Error: ".$this->getError(),
  294. E_USER_WARNING
  295. );
  296. return false;
  297. }
  298. // save the table names in an array and return them
  299. $result = array();
  300. $num = $this->recordCount( $sql );
  301. for( $i = 0; $i < $num; $i++ )
  302. {
  303. $result[] = $this->result( $sql, $i);
  304. }
  305. // save the result in the cache
  306. $this->_cache['tables'] = $result;
  307. return $result;
  308. }
  309. /**
  310. * PostgreSQL::getNotNullFields()
  311. *
  312. * Retrieve the fields that can not contain NULL
  313. *
  314. * @param string $table: The table which fields we should retrieve
  315. * @return array
  316. * @access public
  317. * @author Teye Heimans
  318. */
  319. function getNotNullFields ( $table )
  320. {
  321. $t = strtolower($table);
  322. // return the data from the cache if it exists
  323. if( isset( $this->_cache['notnull'][$t] ) )
  324. {
  325. return $this->_cache['notnull'][$t];
  326. }
  327. $result = array();
  328. $sql = $this->query("
  329. SELECT
  330. a.attname AS name
  331. FROM
  332. pg_class c,
  333. pg_attribute
  334. a,pg_type t
  335. WHERE
  336. relkind = 'r' AND
  337. c.relname='".$table."' AND
  338. a.attnum > 0 AND
  339. a.atttypid = t.oid AND
  340. a.attrelid = c.oid AND
  341. a.attnotnull = true
  342. ORDER BY a.attnum"
  343. );
  344. // query failed ?
  345. if( ! $sql )
  346. {
  347. trigger_error(
  348. "Could not fetch the not-null-fields of the table '".$table."'.\n".
  349. "Query: ".$this->getLastQuery()."\n".
  350. "Error: ".$this->getError(),
  351. E_USER_WARNING
  352. );
  353. return false;
  354. }
  355. while( $row = $this->getRecord($sql) )
  356. {
  357. $result[] = $row['name'];
  358. }
  359. // save the result in the cache
  360. $this->_cache['notnull'][$t] = $result;
  361. return $result;
  362. }
  363. /**
  364. * PostgreSQL::getFieldTypes()
  365. *
  366. * Retrieve the field types of the given table
  367. *
  368. * @param string $table: The table where we should fetch the fields and their types from
  369. * @return array
  370. * @access public
  371. * @author Teye Heimans
  372. */
  373. function getFieldTypes( $table )
  374. {
  375. $t = strtolower($table);
  376. // return the data from the cache if it exists
  377. if( isset( $this->_cache['fieldtypes'][$t] ) )
  378. {
  379. return $this->_cache['fieldtypes'][$t];
  380. }
  381. // Get the default values for the fields
  382. $sql = $this->query("
  383. SELECT
  384. d.adnum as num,
  385. d.adsrc as def
  386. FROM
  387. pg_attrdef d,
  388. pg_class c
  389. WHERE
  390. d.adrelid = c.oid AND
  391. c.relname = '".$table."'
  392. ORDER BY
  393. d.adnum"
  394. );
  395. // query failed ?
  396. if( !$sql )
  397. {
  398. trigger_error(
  399. "Could not fetch the default values for the columns for table '".$table."'.\n".
  400. "Query: ".$this->getLastQuery()."\n".
  401. "Error: ".$this->getError(),
  402. E_USER_NOTICE
  403. );
  404. return false;
  405. }
  406. // walk all the results
  407. $default = array();
  408. while( $row = $this -> getRecord( $sql ) )
  409. {
  410. // is the value a "default" value, or an SQL funtion used by postgre
  411. if( substr($row['def'], 0, 1) == "'" )
  412. {
  413. $s = substr( $row['def'], 1);
  414. $default[$row['num']] = substr($s, 0, strpos($s, "'"));
  415. }
  416. }
  417. // get the meta data
  418. $sql = $this->query("
  419. SELECT
  420. a.attname AS fld,
  421. t.typname AS type,
  422. a.atttypmod AS length,
  423. a.attnum AS num
  424. FROM
  425. pg_class c,
  426. pg_attribute a,
  427. pg_type t
  428. WHERE
  429. relkind = 'r' AND
  430. c.relname='".$table."' AND
  431. a.attnum > 0 AND
  432. a.atttypid = t.oid AND
  433. a.attrelid = c.oid
  434. ORDER BY
  435. a.attnum"
  436. );
  437. // query failed ?
  438. if( !$sql )
  439. {
  440. trigger_error(
  441. "Could not fetch the meta data of the columns for table '".$table."'.\n".
  442. "Query: ".$this->getLastQuery()."\n".
  443. "Error: ".$this->getError(),
  444. E_USER_WARNING
  445. );
  446. return false;
  447. }
  448. $result = array();
  449. while( $row = $this->getRecord( $sql ) )
  450. {
  451. $result[ $row['fld'] ] = array(
  452. $row['type'],
  453. ($row['length'] > 0 ? ($row['length']-4):($row['length']== -1 ? null : $row['length'])),
  454. (array_key_exists( $row['num'], $default) ? $default[$row['num']] : null),
  455. );
  456. }
  457. // save the result in the cache
  458. $this->_cache['fieldtypes'][$t] = $result;
  459. return $result;
  460. }
  461. /**
  462. * PostgreSQL::escapeString()
  463. *
  464. * Escape the string we are going to save from dangerous characters
  465. *
  466. * @param string $string: The string which should be escaped
  467. * @return string
  468. * @access public
  469. * @author Teye Heimans
  470. */
  471. function escapeString( $string )
  472. {
  473. return pg_escape_string( $string );
  474. }
  475. /**
  476. * PostgreSQL::getPrKeys()
  477. *
  478. * Fetch the keys from the table
  479. *
  480. * @param string $table: The table where we should retrieve the keys from
  481. * @return array
  482. * @access public
  483. * @author Teye Heimans
  484. */
  485. function getPrKeys( $table )
  486. {
  487. $t = strtolower($table);
  488. // return the data from the cache if it exists
  489. if( isset( $this->_cache['keys'][$t] ) )
  490. {
  491. return $this->_cache['keys'][$t];
  492. }
  493. $sql = $this->query("
  494. SELECT
  495. a.attname AS column_name
  496. FROM
  497. pg_class bc,
  498. pg_class ic,
  499. pg_index i,
  500. pg_attribute a
  501. WHERE
  502. bc.oid = i.indrelid AND
  503. i.indisprimary = true AND
  504. ic.oid = i.indexrelid AND
  505. (i.indkey[0] = a.attnum OR
  506. i.indkey[1] = a.attnum OR
  507. i.indkey[2] = a.attnum OR
  508. i.indkey[3] = a.attnum OR
  509. i.indkey[4] = a.attnum OR
  510. i.indkey[5] = a.attnum OR
  511. i.indkey[6] = a.attnum OR
  512. i.indkey[7] = a.attnum) AND
  513. a.attrelid = bc.oid AND
  514. bc.relname = '".$table."'"
  515. );
  516. // query failed ?
  517. if( ! $sql )
  518. {
  519. trigger_error(
  520. "Could not fetch the primary key's of the table '".$table."'.\n".
  521. "Query: ".$this->getLastQuery()."\n".
  522. "Error: ".$this->getError(),
  523. E_USER_WARNING
  524. );
  525. return false;
  526. }
  527. $result = array();
  528. while( $row = $this->getRecord($sql) )
  529. {
  530. $result[] = $row['column_name'];
  531. }
  532. // save the result in the cache
  533. $this->_cache['keys'][$t] = $result;
  534. return $result;
  535. }
  536. /**
  537. * PostgreSQL::getUniqueFields()
  538. *
  539. * Fetch the unique keys from the table
  540. *
  541. * @param string $table: The table where we should fetch the unique fields from
  542. * @return array
  543. * @access public
  544. * @author Teye Heimans
  545. */
  546. function getUniqueFields( $table)
  547. {
  548. $t = strtolower( $table );
  549. // return the data from the cache if it exists
  550. if( isset( $this->_cache['unique'][$t] ) )
  551. {
  552. return $this->_cache['unique'][$t];
  553. }
  554. $sql = $this->query("
  555. SELECT
  556. ic.relname AS index_name,
  557. a.attname AS column_name,
  558. i.indisunique AS unique_key,
  559. i.indisprimary AS primary_key
  560. FROM
  561. pg_class bc,
  562. pg_class ic,
  563. pg_index i,
  564. pg_attribute a
  565. WHERE
  566. i.indisunique = true AND
  567. bc.oid = i.indrelid AND
  568. ic.oid = i.indexrelid AND
  569. (i.indkey[0] = a.attnum OR
  570. i.indkey[1] = a.attnum OR
  571. i.indkey[2] = a.attnum OR
  572. i.indkey[3] = a.attnum OR
  573. i.indkey[4] = a.attnum OR
  574. i.indkey[5] = a.attnum OR
  575. i.indkey[6] = a.attnum OR
  576. i.indkey[7] = a.attnum) AND
  577. a.attrelid = bc.oid AND
  578. bc.relname = '".$table."'"
  579. );
  580. // query failed ?
  581. if( ! $sql )
  582. {
  583. trigger_error(
  584. "Could not fetch the unique fields for the table '".$table."'.\n".
  585. "Query: ".$this->getLastQuery()."\n".
  586. "Error: ".$this->getError(),
  587. E_USER_WARNING
  588. );
  589. return false;
  590. }
  591. $result = array();
  592. while( $row = $this->getRecord($sql) )
  593. {
  594. $result[] = $row['column_name'];
  595. }
  596. // save the result in the cache
  597. $this->_cache['unique'][$t] = $result;
  598. return $result;
  599. }
  600. }
  601. ?>