PageRenderTime 74ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/core/db/pgsql.class.php

https://github.com/asterix14/dolibarr
PHP | 1337 lines | 744 code | 137 blank | 456 comment | 132 complexity | 5a1a6350b1d511a3696b28b7e9b7b046 MD5 | raw file
Possible License(s): LGPL-2.0
  1. <?php
  2. /* Copyright (C) 2001 Fabien Seisen <seisen@linuxfr.org>
  3. * Copyright (C) 2002-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  4. * Copyright (C) 2004-2010 Laurent Destailleur <eldy@users.sourceforge.net>
  5. * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
  6. * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
  7. * Copyright (C) 2005-2009 Regis Houssin <regis@dolibarr.fr>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. /**
  23. * \file htdocs/core/db/pgsql.class.php
  24. * \brief Fichier de la classe permettant de gerer une base pgsql
  25. */
  26. /**
  27. * \class DoliDBPgsql
  28. * \brief Class to drive a Postgresql database for Dolibarr
  29. */
  30. class DoliDBPgsql
  31. {
  32. var $db; // Database handler
  33. var $type='pgsql'; // Name of manager
  34. var $label='PostgreSQL'; // Label of manager
  35. //! Charset
  36. var $forcecharset='latin1';
  37. var $versionmin=array(8,4,0); // Version min database
  38. var $results; // Resultset de la derniere requete
  39. var $connected; // 1 si connecte, 0 sinon
  40. var $database_selected; // 1 si base selectionne, 0 sinon
  41. var $database_name; //! Nom base selectionnee
  42. var $database_user; //! Nom user base
  43. var $transaction_opened; // 1 si une transaction est en cours, 0 sinon
  44. var $lastquery;
  45. var $lastqueryerror; // Ajout d'une variable en cas d'erreur
  46. var $unescapeslashquot=0; // By default we do not force the unescape of \'. This is used only to process sql with mysql escaped data.
  47. var $standard_conforming_strings=1; // Database has option standard_conforming_strings to on
  48. var $ok;
  49. var $error;
  50. var $lasterror;
  51. /**
  52. * Constructor.
  53. * This create an opened connexion to a database server and eventually to a database
  54. *
  55. * @param string $type Type of database (mysql, pgsql...)
  56. * @param string $host Address of database server
  57. * @param string $user Nom de l'utilisateur autorise
  58. * @param string $pass Mot de passe
  59. * @param string $name Nom de la database
  60. * @param int $port Port of database server
  61. * @return int 1 if OK, 0 if not
  62. */
  63. function DoliDBPgsql($type, $host, $user, $pass, $name='', $port=0)
  64. {
  65. global $conf,$langs;
  66. $this->forcecharset=$conf->file->character_set_client;
  67. $this->forcecollate=$conf->db->dolibarr_main_db_collation;
  68. $this->database_user=$user;
  69. $this->transaction_opened=0;
  70. //print "Name DB: $host,$user,$pass,$name<br>";
  71. if (! function_exists("pg_connect"))
  72. {
  73. $this->connected = 0;
  74. $this->ok = 0;
  75. $this->error="Pgsql PHP functions are not available in this version of PHP";
  76. dol_syslog("DoliDB::DoliDB : Pgsql PHP functions are not available in this version of PHP",LOG_ERR);
  77. return $this->ok;
  78. }
  79. if (! $host)
  80. {
  81. $this->connected = 0;
  82. $this->ok = 0;
  83. $this->error=$langs->trans("ErrorWrongHostParameter");
  84. dol_syslog("DoliDB::DoliDB : Erreur Connect, wrong host parameters",LOG_ERR);
  85. return $this->ok;
  86. }
  87. // Essai connexion serveur
  88. //print "$host, $user, $pass, $name, $port";
  89. $this->db = $this->connect($host, $user, $pass, $name, $port);
  90. if ($this->db)
  91. {
  92. $this->connected = 1;
  93. $this->ok = 1;
  94. }
  95. else
  96. {
  97. // host, login ou password incorrect
  98. $this->connected = 0;
  99. $this->ok = 0;
  100. $this->error='Host, login or password incorrect';
  101. dol_syslog("DoliDB::DoliDB : Erreur Connect ".$this->error,LOG_ERR);
  102. }
  103. // Si connexion serveur ok et si connexion base demandee, on essaie connexion base
  104. if ($this->connected && $name)
  105. {
  106. if ($this->select_db($name))
  107. {
  108. $this->database_selected = 1;
  109. $this->database_name = $name;
  110. $this->ok = 1;
  111. }
  112. else
  113. {
  114. $this->database_selected = 0;
  115. $this->database_name = '';
  116. $this->ok = 0;
  117. $this->error=$this->error();
  118. dol_syslog("DoliDB::DoliDB : Erreur Select_db ".$this->error,LOG_ERR);
  119. }
  120. }
  121. else
  122. {
  123. // Pas de selection de base demandee, ok ou ko
  124. $this->database_selected = 0;
  125. }
  126. return $this->ok;
  127. }
  128. /**
  129. * Convert a SQL request in Mysql syntax to native syntax
  130. *
  131. * @param string $line SQL request line to convert
  132. * @param string $type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
  133. * @return string SQL request line converted
  134. */
  135. function convertSQLFromMysql($line,$type='auto')
  136. {
  137. // Removed empty line if this is a comment line for SVN tagging
  138. if (preg_match('/^--\s\$Id/i',$line)) {
  139. return '';
  140. }
  141. // Return line if this is a comment
  142. if (preg_match('/^#/i',$line) || preg_match('/^$/i',$line) || preg_match('/^--/i',$line))
  143. {
  144. return $line;
  145. }
  146. if ($line != "")
  147. {
  148. if ($type == 'auto')
  149. {
  150. if (preg_match('/ALTER TABLE/i',$line)) $type='dml';
  151. else if (preg_match('/CREATE TABLE/i',$line)) $type='dml';
  152. else if (preg_match('/DROP TABLE/i',$line)) $type='dml';
  153. }
  154. if ($type == 'dml')
  155. {
  156. $line=preg_replace('/\s/',' ',$line); // Replace tabulation with space
  157. // we are inside create table statement so lets process datatypes
  158. if (preg_match('/(ISAM|innodb)/i',$line)) { // end of create table sequence
  159. $line=preg_replace('/\)[\s\t]*type[\s\t]*=[\s\t]*(MyISAM|innodb);/i',');',$line);
  160. $line=preg_replace('/\)[\s\t]*engine[\s\t]*=[\s\t]*(MyISAM|innodb);/i',');',$line);
  161. $line=preg_replace('/,$/','',$line);
  162. }
  163. // Process case: "CREATE TABLE llx_mytable(rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,code..."
  164. if (preg_match('/[\s\t\(]*(\w*)[\s\t]+int.*auto_increment/i',$line,$reg)) {
  165. $newline=preg_replace('/([\s\t\(]*)([a-zA-Z_0-9]*)[\s\t]+int.*auto_increment[^,]*/i','\\1 \\2 SERIAL PRIMARY KEY',$line);
  166. //$line = "-- ".$line." replaced by --\n".$newline;
  167. $line=$newline;
  168. }
  169. // tinyint type conversion
  170. $line=str_replace('tinyint','smallint',$line);
  171. // nuke unsigned
  172. $line=preg_replace('/(int\w+|smallint)\s+unsigned/i','\\1',$line);
  173. // blob -> text
  174. $line=preg_replace('/\w*blob/i','text',$line);
  175. // tinytext/mediumtext -> text
  176. $line=preg_replace('/tinytext/i','text',$line);
  177. $line=preg_replace('/mediumtext/i','text',$line);
  178. // change not null datetime field to null valid ones
  179. // (to support remapping of "zero time" to null
  180. $line=preg_replace('/datetime not null/i','datetime',$line);
  181. $line=preg_replace('/datetime/i','timestamp',$line);
  182. // double -> numeric
  183. $line=preg_replace('/^double/i','numeric',$line);
  184. $line=preg_replace('/(\s*)double/i','\\1numeric',$line);
  185. // float -> numeric
  186. $line=preg_replace('/^float/i','numeric',$line);
  187. $line=preg_replace('/(\s*)float/i','\\1numeric',$line);
  188. // unique index(field1,field2)
  189. if (preg_match('/unique index\s*\((\w+\s*,\s*\w+)\)/i',$line))
  190. {
  191. $line=preg_replace('/unique index\s*\((\w+\s*,\s*\w+)\)/i','UNIQUE\(\\1\)',$line);
  192. }
  193. // We remove end of requests "AFTER fieldxxx"
  194. $line=preg_replace('/AFTER [a-z0-9_]+/i','',$line);
  195. // We remove start of requests "ALTER TABLE tablexxx" if this is a DROP INDEX
  196. $line=preg_replace('/ALTER TABLE [a-z0-9_]+ DROP INDEX/i','DROP INDEX',$line);
  197. // Translate order to rename fields
  198. if (preg_match('/ALTER TABLE ([a-z0-9_]+) CHANGE(?: COLUMN)? ([a-z0-9_]+) ([a-z0-9_]+)(.*)$/i',$line,$reg))
  199. {
  200. $line = "-- ".$line." replaced by --\n";
  201. $line.= "ALTER TABLE ".$reg[1]." RENAME COLUMN ".$reg[2]." TO ".$reg[3];
  202. }
  203. // Translate order to modify field format
  204. if (preg_match('/ALTER TABLE ([a-z0-9_]+) MODIFY(?: COLUMN)? ([a-z0-9_]+) (.*)$/i',$line,$reg))
  205. {
  206. $line = "-- ".$line." replaced by --\n";
  207. $newreg3=$reg[3];
  208. $newreg3=preg_replace('/ DEFAULT NULL/i','',$newreg3);
  209. $newreg3=preg_replace('/ NOT NULL/i','',$newreg3);
  210. $newreg3=preg_replace('/ NULL/i','',$newreg3);
  211. $newreg3=preg_replace('/ DEFAULT 0/i','',$newreg3);
  212. $newreg3=preg_replace('/ DEFAULT \'[0-9a-zA-Z_@]*\'/i','',$newreg3);
  213. $line.= "ALTER TABLE ".$reg[1]." ALTER COLUMN ".$reg[2]." TYPE ".$newreg3;
  214. // TODO Add alter to set default value or null/not null if there is this in $reg[3]
  215. }
  216. // alter table add primary key (field1, field2 ...) -> We remove the primary key name not accepted by PostGreSQL
  217. // ALTER TABLE llx_dolibarr_modules ADD PRIMARY KEY pk_dolibarr_modules (numero, entity);
  218. if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+PRIMARY\s+KEY\s*(.*)\s*\((.*)$/i',$line,$reg))
  219. {
  220. $line = "-- ".$line." replaced by --\n";
  221. $line.= "ALTER TABLE ".$reg[1]." ADD PRIMARY KEY (".$reg[3];
  222. }
  223. // Translate order to drop foreign keys
  224. // ALTER TABLE llx_dolibarr_modules DROP FOREIGN KEY fk_xxx;
  225. if (preg_match('/ALTER\s+TABLE\s*(.*)\s*DROP\s+FOREIGN\s+KEY\s*(.*)$/i',$line,$reg))
  226. {
  227. $line = "-- ".$line." replaced by --\n";
  228. $line.= "ALTER TABLE ".$reg[1]." DROP CONSTRAINT ".$reg[2];
  229. }
  230. // alter table add [unique] [index] (field1, field2 ...)
  231. // ALTER TABLE llx_accountingaccount ADD INDEX idx_accountingaccount_fk_pcg_version (fk_pcg_version)
  232. if (preg_match('/ALTER\s+TABLE\s*(.*)\s*ADD\s+(UNIQUE INDEX|INDEX|UNIQUE)\s+(.*)\s*\(([\w,\s]+)\)/i',$line,$reg))
  233. {
  234. $fieldlist=$reg[4];
  235. $idxname=$reg[3];
  236. $tablename=$reg[1];
  237. $line = "-- ".$line." replaced by --\n";
  238. $line.= "CREATE ".(preg_match('/UNIQUE/',$reg[2])?'UNIQUE ':'')."INDEX ".$idxname." ON ".$tablename." (".$fieldlist.")";
  239. }
  240. }
  241. // To have postgresql case sensitive
  242. $line=str_replace(' LIKE \'',' ILIKE \'',$line);
  243. // Delete using criteria on other table must not declare twice the deleted table
  244. // DELETE FROM tabletodelete USING tabletodelete, othertable -> DELETE FROM tabletodelete USING othertable
  245. if (preg_match('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i',$line,$reg))
  246. {
  247. if ($reg[1] == $reg[2]) // If same table, we remove second one
  248. {
  249. $line=preg_replace('/DELETE FROM ([a-z_]+) USING ([a-z_]+), ([a-z_]+)/i','DELETE FROM \\1 USING \\3', $line);
  250. }
  251. }
  252. // Remove () in the tables in FROM if one table
  253. $line=preg_replace('/FROM\s*\((([a-z_]+)\s+as\s+([a-z_]+)\s*)\)/i','FROM \\1',$line);
  254. //print $line."\n";
  255. // Remove () in the tables in FROM if two table
  256. $line=preg_replace('/FROM\s*\(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*)\)/i','FROM \\1, \\2',$line);
  257. //print $line."\n";
  258. // Remove () in the tables in FROM if two table
  259. $line=preg_replace('/FROM\s*\(([a-z_]+\s+as\s+[a-z_]+)\s*,\s*([a-z_]+\s+as\s+[a-z_]+\s*),\s*([a-z_]+\s+as\s+[a-z_]+\s*)\)/i','FROM \\1, \\2, \\3',$line);
  260. //print $line."\n";
  261. // Replace espacing \' by ''.
  262. // By default we do not (should be already done by db->escape function if required)
  263. if (! empty($this->unescapeslashquot))
  264. {
  265. // Except for sql insert in data file that
  266. // are mysql escaped so we removed them to be compatible with standard_conforming_strings=on
  267. // that considers \ as ordinary character).
  268. if ($this->standard_conforming_strings)
  269. {
  270. $line=preg_replace("/\\\'/","''",$line);
  271. }
  272. }
  273. //print "type=".$type." newline=".$line."<br>\n";
  274. }
  275. return $line;
  276. }
  277. /**
  278. * Select a database
  279. * Ici postgresql n'a aucune fonction equivalente de mysql_select_db
  280. * On compare juste manuellement si la database choisie est bien celle activee par la connexion
  281. *
  282. * @param string $database Name of database
  283. * @return boolean true if OK, false if KO
  284. */
  285. function select_db($database)
  286. {
  287. if ($database == $this->database_name) return true;
  288. else return false;
  289. }
  290. /**
  291. * Connexion to server
  292. *
  293. * @param string $host database server host
  294. * @param string $login login
  295. * @param string $passwd password
  296. * @param string $name name of database (not used for mysql, used for pgsql)
  297. * @param string $port Port of database server
  298. * @return resource Database access handler
  299. * @see close
  300. */
  301. function connect($host, $login, $passwd, $name, $port=0)
  302. {
  303. if (!$name){
  304. $name="postgres";
  305. }
  306. if (!$port){
  307. $port=5432;
  308. }
  309. $con_string = "host=$host port=$port dbname=$name user=$login password=$passwd";
  310. //print 'xxx'.$con_string;
  311. //$this->db = pg_pconnect($con_string); // To us persistent connection because this one cost 1ms, non ersisten cost 30ms
  312. $this->db = pg_connect($con_string);
  313. if ($this->db)
  314. {
  315. $this->database_name = $name;
  316. pg_set_error_verbosity($this->db, PGSQL_ERRORS_VERBOSE); // Set verbosity to max
  317. }
  318. return $this->db;
  319. }
  320. /**
  321. * Return label of manager
  322. *
  323. * @return string Label
  324. */
  325. function getLabel()
  326. {
  327. return $this->label;
  328. }
  329. /**
  330. * Return version of database server
  331. *
  332. * @return string Version string
  333. */
  334. function getVersion()
  335. {
  336. $resql=$this->query('SHOW server_version');
  337. if ($resql)
  338. {
  339. $liste=$this->fetch_array($resql);
  340. return $liste['server_version'];
  341. }
  342. return '';
  343. }
  344. /**
  345. * Return version of database server into an array
  346. *
  347. * @return array Version array
  348. */
  349. function getVersionArray()
  350. {
  351. return explode('.',$this->getVersion());
  352. }
  353. /**
  354. * Close database connexion
  355. *
  356. * @return boolean True if disconnect successfull, false otherwise
  357. * @see connect
  358. */
  359. function close()
  360. {
  361. if ($this->db)
  362. {
  363. //dol_syslog("DoliDB::disconnect",LOG_DEBUG);
  364. $this->connected=0;
  365. return pg_close($this->db);
  366. }
  367. return false;
  368. }
  369. /**
  370. * Start transaction
  371. *
  372. * @return int 1 if transaction successfuly opened or already opened, 0 if error
  373. */
  374. function begin()
  375. {
  376. if (! $this->transaction_opened)
  377. {
  378. $ret=$this->query("BEGIN;");
  379. if ($ret)
  380. {
  381. $this->transaction_opened++;
  382. dol_syslog("BEGIN Transaction",LOG_DEBUG);
  383. }
  384. return $ret;
  385. }
  386. else
  387. {
  388. $this->transaction_opened++;
  389. return 1;
  390. }
  391. }
  392. /**
  393. * Validate a database transaction
  394. *
  395. * @param log Add more log to default log line
  396. * @return int 1 if validation is OK or transaction level no started, 0 if ERROR
  397. */
  398. function commit($log='')
  399. {
  400. if ($this->transaction_opened<=1)
  401. {
  402. $ret=$this->query("COMMIT;");
  403. if ($ret)
  404. {
  405. $this->transaction_opened=0;
  406. dol_syslog("COMMIT Transaction",LOG_DEBUG);
  407. }
  408. return $ret;
  409. }
  410. else
  411. {
  412. $this->transaction_opened--;
  413. return 1;
  414. }
  415. }
  416. /**
  417. * Annulation d'une transaction et retour aux anciennes valeurs
  418. * @return int 1 si annulation ok ou transaction non ouverte, 0 en cas d'erreur
  419. */
  420. function rollback()
  421. {
  422. if ($this->transaction_opened<=1)
  423. {
  424. $ret=$this->query("ROLLBACK;");
  425. $this->transaction_opened=0;
  426. dol_syslog("ROLLBACK Transaction",LOG_DEBUG);
  427. return $ret;
  428. }
  429. else
  430. {
  431. $this->transaction_opened--;
  432. return 1;
  433. }
  434. }
  435. /**
  436. * Convert request to PostgreSQL syntax, execute it and return the resultset
  437. *
  438. * @param query SQL query string
  439. * @param usesavepoint 0=Default mode, 1=Run a savepoint before and a rollback to savepoint if error (this allow to have some request with errors inside global transactions).
  440. * @param type Type of SQL order ('ddl' for insert, update, select, delete or 'dml' for create, alter...)
  441. * @return resource Resultset of answer
  442. */
  443. function query($query,$usesavepoint=0,$type='auto')
  444. {
  445. $query = trim($query);
  446. // Convert MySQL syntax to PostgresSQL syntax
  447. $query=$this->convertSQLFromMysql($query,$type);
  448. //print "FF\n".$query."<br>\n";
  449. // Fix bad formed requests. If request contains a date without quotes, we fix this but this should not occurs.
  450. $loop=true;
  451. while ($loop)
  452. {
  453. if (preg_match('/([^\'])([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9])/',$query))
  454. {
  455. $query=preg_replace('/([^\'])([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9])/','\\1\'\\2\'',$query);
  456. dol_syslog("Warning: Bad formed request converted into ".$query,LOG_WARNING);
  457. }
  458. else $loop=false;
  459. }
  460. if ($usesavepoint && $this->transaction_opened)
  461. {
  462. @pg_query($this->db, 'SAVEPOINT mysavepoint');
  463. }
  464. $ret = @pg_query($this->db, $query);
  465. //print $query;
  466. if (! preg_match("/^COMMIT/i",$query) && ! preg_match("/^ROLLBACK/i",$query)) // Si requete utilisateur, on la sauvegarde ainsi que son resultset
  467. {
  468. if (! $ret)
  469. {
  470. $this->lastqueryerror = $query;
  471. $this->lasterror = $this->error();
  472. $this->lasterrno = $this->errno();
  473. dol_syslog("Pgsql.lib::query SQL error: ".$query." ".$this->lasterrno, LOG_WARNING);
  474. //print "\n>> ".$query."<br>\n";
  475. //print '>> '.$this->lasterrno.' - '.$this->lasterror.' - '.$this->lastqueryerror."<br>\n";
  476. if ($usesavepoint && $this->transaction_opened)
  477. {
  478. @pg_query($this->db, 'ROLLBACK TO SAVEPOINT mysavepoint');
  479. }
  480. }
  481. $this->lastquery=$query;
  482. $this->results = $ret;
  483. }
  484. return $ret;
  485. }
  486. /**
  487. * Renvoie la ligne courante (comme un objet) pour le curseur resultset
  488. *
  489. * @param resultset Curseur de la requete voulue
  490. * @return object Object result line or false if KO or end of cursor
  491. */
  492. function fetch_object($resultset)
  493. {
  494. // If resultset not provided, we take the last used by connexion
  495. if (! is_resource($resultset)) { $resultset=$this->results; }
  496. return pg_fetch_object($resultset);
  497. }
  498. /**
  499. * Renvoie les donnees dans un tableau
  500. *
  501. * @param resultset Curseur de la requete voulue
  502. * @return array
  503. */
  504. function fetch_array($resultset)
  505. {
  506. // If resultset not provided, we take the last used by connexion
  507. if (! is_resource($resultset)) { $resultset=$this->results; }
  508. return pg_fetch_array($resultset);
  509. }
  510. /**
  511. * Renvoie les donnees comme un tableau
  512. *
  513. * @param resultset Curseur de la requete voulue
  514. * @return array
  515. */
  516. function fetch_row($resultset)
  517. {
  518. // Si le resultset n'est pas fourni, on prend le dernier utilise sur cette connexion
  519. if (! is_resource($resultset)) { $resultset=$this->results; }
  520. return pg_fetch_row($resultset);
  521. }
  522. /**
  523. * Renvoie le nombre de lignes dans le resultat d'une requete SELECT
  524. *
  525. * @see affected_rows
  526. * @param resultset Curseur de la requete voulue
  527. * @return int Nombre de lignes
  528. */
  529. function num_rows($resultset)
  530. {
  531. // If resultset not provided, we take the last used by connexion
  532. if (! is_resource($resultset)) { $resultset=$this->results; }
  533. return pg_num_rows($resultset);
  534. }
  535. /**
  536. * Renvoie le nombre de lignes dans le resultat d'une requete INSERT, DELETE ou UPDATE
  537. *
  538. * @see num_rows
  539. * @param resultset Curseur de la requete voulue
  540. * @return int Nombre de lignes
  541. */
  542. function affected_rows($resultset)
  543. {
  544. // If resultset not provided, we take the last used by connexion
  545. if (! is_resource($resultset)) { $resultset=$this->results; }
  546. // pgsql necessite un resultset pour cette fonction contrairement
  547. // a mysql qui prend un link de base
  548. return pg_affected_rows($resultset);
  549. }
  550. /**
  551. * Libere le dernier resultset utilise sur cette connexion
  552. *
  553. * @param resultset Curseur de la requete voulue
  554. */
  555. function free($resultset=0)
  556. {
  557. // If resultset not provided, we take the last used by connexion
  558. if (! is_resource($resultset)) { $resultset=$this->results; }
  559. // Si resultset en est un, on libere la memoire
  560. if (is_resource($resultset)) pg_free_result($resultset);
  561. }
  562. /**
  563. * Defini les limites de la requete
  564. *
  565. * @param limit nombre maximum de lignes retournees
  566. * @param offset numero de la ligne a partir de laquelle recuperer les lignes
  567. * @return string chaine exprimant la syntax sql de la limite
  568. */
  569. function plimit($limit=0,$offset=0)
  570. {
  571. global $conf;
  572. if (! $limit) $limit=$conf->liste_limit;
  573. if ($offset > 0) return " LIMIT ".$limit." OFFSET ".$offset." ";
  574. else return " LIMIT $limit ";
  575. }
  576. /**
  577. * Define sort criteria of request
  578. *
  579. * @param sortfield List of sort fields
  580. * @param sortorder Sort order
  581. * @return string String to provide syntax of a sort sql string
  582. * TODO Mutualized this into a mother class
  583. */
  584. function order($sortfield=0,$sortorder=0)
  585. {
  586. if ($sortfield)
  587. {
  588. $return='';
  589. $fields=explode(',',$sortfield);
  590. foreach($fields as $val)
  591. {
  592. if (! $return) $return.=' ORDER BY ';
  593. else $return.=',';
  594. $return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
  595. if ($sortorder) $return.=' '.preg_replace('/[^0-9a-z]/i','',$sortorder);
  596. }
  597. return $return;
  598. }
  599. else
  600. {
  601. return '';
  602. }
  603. }
  604. /**
  605. * Escape a string to insert data
  606. *
  607. * @param stringtoencode String to escape
  608. * @return string String escaped
  609. */
  610. function escape($stringtoencode)
  611. {
  612. return pg_escape_string($stringtoencode);
  613. }
  614. /**
  615. * Convert (by PHP) a GM Timestamp date into a GM string date to insert into a date field.
  616. * Function to use to build INSERT, UPDATE or WHERE predica
  617. *
  618. * @param param Date TMS to convert
  619. * @return string Date in a string YYYYMMDDHHMMSS
  620. */
  621. function idate($param)
  622. {
  623. return adodb_strftime("%Y-%m-%d %H:%M:%S",$param);
  624. }
  625. /**
  626. * Convert (by PHP) a PHP server TZ string date into a GM Timestamps date
  627. * 19700101020000 -> 3600 with TZ+1
  628. *
  629. * @param string Date in a string (YYYYMMDDHHMMSS, YYYYMMDD, YYYY-MM-DD HH:MM:SS)
  630. * @return date Date TMS
  631. */
  632. function jdate($string)
  633. {
  634. $string=preg_replace('/([^0-9])/i','',$string);
  635. $tmp=$string.'000000';
  636. $date=dol_mktime(substr($tmp,8,2),substr($tmp,10,2),substr($tmp,12,2),substr($tmp,4,2),substr($tmp,6,2),substr($tmp,0,4));
  637. return $date;
  638. }
  639. /**
  640. * Formate a SQL IF
  641. *
  642. * @param test chaine test
  643. * @param resok resultat si test egal
  644. * @param resko resultat si test non egal
  645. * @return string chaine formate SQL
  646. */
  647. function ifsql($test,$resok,$resko)
  648. {
  649. return '(CASE WHEN '.$test.' THEN '.$resok.' ELSE '.$resko.' END)';
  650. }
  651. /**
  652. * Renvoie la derniere requete soumise par la methode query()
  653. *
  654. * @return lastquery
  655. */
  656. function lastquery()
  657. {
  658. return $this->lastquery;
  659. }
  660. /**
  661. * Renvoie la derniere requete en erreur
  662. *
  663. * @return string lastqueryerror
  664. */
  665. function lastqueryerror()
  666. {
  667. return $this->lastqueryerror;
  668. }
  669. /**
  670. * Renvoie le libelle derniere erreur
  671. *
  672. * @return string lasterror
  673. */
  674. function lasterror()
  675. {
  676. return $this->lasterror;
  677. }
  678. /**
  679. * Renvoie le code derniere erreur
  680. *
  681. * @return string lasterrno
  682. */
  683. function lasterrno()
  684. {
  685. return $this->lasterrno;
  686. }
  687. /**
  688. * Renvoie le code erreur generique de l'operation precedente.
  689. *
  690. * @return error_num (Exemples: DB_ERROR_TABLE_ALREADY_EXISTS, DB_ERROR_RECORD_ALREADY_EXISTS...)
  691. */
  692. function errno()
  693. {
  694. if (! $this->connected) {
  695. // Si il y a eu echec de connexion, $this->db n'est pas valide.
  696. return 'DB_ERROR_FAILED_TO_CONNECT';
  697. }
  698. else {
  699. // Constants to convert a MySql error code to a generic Dolibarr error code
  700. $errorcode_map = array(
  701. 1004 => 'DB_ERROR_CANNOT_CREATE',
  702. 1005 => 'DB_ERROR_CANNOT_CREATE',
  703. 1006 => 'DB_ERROR_CANNOT_CREATE',
  704. 1007 => 'DB_ERROR_ALREADY_EXISTS',
  705. 1008 => 'DB_ERROR_CANNOT_DROP',
  706. 1025 => 'DB_ERROR_NO_FOREIGN_KEY_TO_DROP',
  707. 1044 => 'DB_ERROR_ACCESSDENIED',
  708. 1046 => 'DB_ERROR_NODBSELECTED',
  709. 1048 => 'DB_ERROR_CONSTRAINT',
  710. '42P07' => 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS',
  711. '42703' => 'DB_ERROR_NOSUCHFIELD',
  712. 1060 => 'DB_ERROR_COLUMN_ALREADY_EXISTS',
  713. 42701=> 'DB_ERROR_COLUMN_ALREADY_EXISTS',
  714. '42710' => 'DB_ERROR_KEY_NAME_ALREADY_EXISTS',
  715. '23505' => 'DB_ERROR_RECORD_ALREADY_EXISTS',
  716. '42704' => 'DB_ERROR_NO_INDEX_TO_DROP',
  717. '42601' => 'DB_ERROR_SYNTAX',
  718. '42P16' => 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS',
  719. 1075 => 'DB_ERROR_CANT_DROP_PRIMARY_KEY',
  720. 1091 => 'DB_ERROR_NOSUCHFIELD',
  721. 1100 => 'DB_ERROR_NOT_LOCKED',
  722. 1136 => 'DB_ERROR_VALUE_COUNT_ON_ROW',
  723. '42P01' => 'DB_ERROR_NOSUCHTABLE',
  724. '23503' => 'DB_ERROR_NO_PARENT',
  725. 1217 => 'DB_ERROR_CHILD_EXISTS',
  726. 1451 => 'DB_ERROR_CHILD_EXISTS',
  727. '42P04' => 'DB_DATABASE_ALREADY_EXISTS'
  728. );
  729. $errorlabel=pg_last_error($this->db);
  730. $errorcode='';
  731. if (preg_match('/: *([0-9P]+):/',$errorlabel,$reg))
  732. {
  733. $errorcode=$reg[1];
  734. if (isset($errorcode_map[$errorcode]))
  735. {
  736. return $errorcode_map[$errorcode];
  737. }
  738. }
  739. $errno=$errorcode?$errorcode:$errorlabel;
  740. return ($errno?'DB_ERROR_'.$errno:'0');
  741. }
  742. // '/(Table does not exist\.|Relation [\"\'].*[\"\'] does not exist|sequence does not exist|class ".+" not found)$/' => 'DB_ERROR_NOSUCHTABLE',
  743. // '/table [\"\'].*[\"\'] does not exist/' => 'DB_ERROR_NOSUCHTABLE',
  744. // '/Relation [\"\'].*[\"\'] already exists|Cannot insert a duplicate key into (a )?unique index.*/' => 'DB_ERROR_RECORD_ALREADY_EXISTS',
  745. // '/divide by zero$/' => 'DB_ERROR_DIVZERO',
  746. // '/pg_atoi: error in .*: can\'t parse /' => 'DB_ERROR_INVALID_NUMBER',
  747. // '/ttribute [\"\'].*[\"\'] not found$|Relation [\"\'].*[\"\'] does not have attribute [\"\'].*[\"\']/' => 'DB_ERROR_NOSUCHFIELD',
  748. // '/parser: parse error at or near \"/' => 'DB_ERROR_SYNTAX',
  749. // '/referential integrity violation/' => 'DB_ERROR_CONSTRAINT'
  750. }
  751. /**
  752. * Renvoie le texte de l'erreur pgsql de l'operation precedente
  753. *
  754. * @return error_text
  755. */
  756. function error()
  757. {
  758. return pg_last_error($this->db);
  759. }
  760. /**
  761. * Get last ID after an insert INSERT
  762. *
  763. * @param tab Table name concerned by insert. Ne sert pas sous MySql mais requis pour compatibilite avec Postgresql
  764. * @return int id
  765. */
  766. function last_insert_id($tab,$fieldid='rowid')
  767. {
  768. //$result = pg_query($this->db,"SELECT MAX(".$fieldid.") FROM ".$tab);
  769. $result = pg_query($this->db,"SELECT currval('".$tab."_".$fieldid."_seq')");
  770. if (! $result)
  771. {
  772. print pg_last_error($this->db);
  773. exit;
  774. }
  775. //$nbre = pg_num_rows($result);
  776. $row = pg_fetch_result($result,0,0);
  777. return $row;
  778. }
  779. /**
  780. * Encrypt sensitive data in database
  781. * Warning: This function includes the escape, so it must use direct value
  782. *
  783. * @param fieldorvalue Field name or value to encrypt
  784. * @param withQuotes Return string with quotes
  785. * @return return XXX(field) or XXX('value') or field or 'value'
  786. */
  787. function encrypt($fieldorvalue, $withQuotes=0)
  788. {
  789. global $conf;
  790. // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
  791. $cryptType = ($conf->db->dolibarr_main_db_encryption?$conf->db->dolibarr_main_db_encryption:0);
  792. //Encryption key
  793. $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey)?$conf->db->dolibarr_main_db_cryptkey:'');
  794. $return = $fieldorvalue;
  795. return ($withQuotes?"'":"").$this->escape($return).($withQuotes?"'":"");
  796. }
  797. /**
  798. * Decrypt sensitive data in database
  799. *
  800. * @param value Value to decrypt
  801. * @return return Decrypted value if used
  802. */
  803. function decrypt($value)
  804. {
  805. global $conf;
  806. // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption)
  807. $cryptType = ($conf->db->dolibarr_main_db_encryption?$conf->db->dolibarr_main_db_encryption:0);
  808. //Encryption key
  809. $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey)?$conf->db->dolibarr_main_db_cryptkey:'');
  810. $return = $value;
  811. return $return;
  812. }
  813. // Next function are not required. Only minor features use them.
  814. //--------------------------------------------------------------
  815. /**
  816. * Renvoie l'id de la connexion
  817. *
  818. * @return string Id connexion
  819. */
  820. function DDLGetConnectId()
  821. {
  822. return '?';
  823. }
  824. /**
  825. * Create a new database
  826. * Ne pas utiliser les fonctions xxx_create_db (xxx=mysql, ...) car elles sont deprecated
  827. *
  828. * @param database Database name to create
  829. * @param charset Charset used to store data
  830. * @param collation Charset used to sort data
  831. * @param owner Username of database owner
  832. * @return resource resource defined if OK, null if KO
  833. */
  834. function DDLCreateDb($database,$charset='',$collation='',$owner='')
  835. {
  836. if (empty($charset)) $charset=$this->forcecharset;
  837. if (empty($collation)) $collation=$this->collation;
  838. $ret=$this->query('CREATE DATABASE '.$database.' OWNER '.$owner.' ENCODING \''.$charset.'\'');
  839. return $ret;
  840. }
  841. /**
  842. * Liste des tables dans une database.
  843. * @param database Nom de la database
  844. * @return resource
  845. */
  846. function DDLListTables($database, $table='')
  847. {
  848. $listtables=array();
  849. $like = '';
  850. if ($table) $like = " AND table_name LIKE '".$table."'";
  851. $result = pg_query($this->db, "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'".$like." ORDER BY table_name");
  852. while($row = $this->fetch_row($result))
  853. {
  854. $listtables[] = $row[0];
  855. }
  856. return $listtables;
  857. }
  858. /**
  859. * Liste les informations des champs d'une table.
  860. * @param table Nom de la table
  861. * @return array Tableau des informations des champs de la table
  862. * TODO modifier pour postgresql
  863. */
  864. function DDLInfoTable($table)
  865. {
  866. /*
  867. $infotables=array();
  868. $sql="SHOW FULL COLUMNS FROM ".$table.";";
  869. dol_syslog($sql,LOG_DEBUG);
  870. $result = $this->pg_query($this->db,$sql);
  871. while($row = $this->fetch_row($result))
  872. {
  873. $infotables[] = $row;
  874. }
  875. return $infotables;
  876. */
  877. }
  878. /**
  879. * Create a table into database
  880. *
  881. * @param string $table Nom de la table
  882. * @param array $fields Tableau associatif [nom champ][tableau des descriptions]
  883. * @param string $primary_key Nom du champ qui sera la clef primaire
  884. * @param string $type Type de la table
  885. * @param array $unique_keys Tableau associatifs Nom de champs qui seront clef unique => valeur
  886. * @param array $fulltext_keys Tableau des Nom de champs qui seront indexes en fulltext
  887. * @param string $keys Tableau des champs cles noms => valeur
  888. * @return int <0 if KO, >=0 if OK
  889. */
  890. function DDLCreateTable($table,$fields,$primary_key,$type,$unique_keys="",$fulltext_keys="",$keys="")
  891. {
  892. // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra
  893. // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
  894. $sql = "create table ".$table."(";
  895. $i=0;
  896. foreach($fields as $field_name => $field_desc)
  897. {
  898. $sqlfields[$i] = $field_name." ";
  899. $sqlfields[$i] .= $field_desc['type'];
  900. if( preg_match("/^[^\s]/i",$field_desc['value']))
  901. $sqlfields[$i] .= "(".$field_desc['value'].")";
  902. else if( preg_match("/^[^\s]/i",$field_desc['attribute']))
  903. $sqlfields[$i] .= " ".$field_desc['attribute'];
  904. else if( preg_match("/^[^\s]/i",$field_desc['default']))
  905. {
  906. if(preg_match("/null/i",$field_desc['default']))
  907. $sqlfields[$i] .= " default ".$field_desc['default'];
  908. else
  909. $sqlfields[$i] .= " default '".$field_desc['default']."'";
  910. }
  911. else if( preg_match("/^[^\s]/i",$field_desc['null']))
  912. $sqlfields[$i] .= " ".$field_desc['null'];
  913. else if( preg_match("/^[^\s]/i",$field_desc['extra']))
  914. $sqlfields[$i] .= " ".$field_desc['extra'];
  915. $i++;
  916. }
  917. if($primary_key != "")
  918. $pk = "primary key(".$primary_key.")";
  919. if($unique_keys != "")
  920. {
  921. $i = 0;
  922. foreach($unique_keys as $key => $value)
  923. {
  924. $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$value."')";
  925. $i++;
  926. }
  927. }
  928. if($keys != "")
  929. {
  930. $i = 0;
  931. foreach($keys as $key => $value)
  932. {
  933. $sqlk[$i] = "KEY ".$key." (".$value.")";
  934. $i++;
  935. }
  936. }
  937. $sql .= implode(',',$sqlfields);
  938. if($primary_key != "")
  939. $sql .= ",".$pk;
  940. if($unique_keys != "")
  941. $sql .= ",".implode(',',$sqluq);
  942. if($keys != "")
  943. $sql .= ",".implode(',',$sqlk);
  944. $sql .=") type=".$type;
  945. dol_syslog($sql,LOG_DEBUG);
  946. if(! $this->query($sql))
  947. return -1;
  948. else
  949. return 1;
  950. }
  951. /**
  952. * Create a user
  953. *
  954. * @param dolibarr_main_db_host Ip serveur
  955. * @param dolibarr_main_db_user Nom user a creer
  956. * @param dolibarr_main_db_pass Mot de passe user a creer
  957. * @param dolibarr_main_db_name Database name where user must be granted
  958. * @return int <0 si KO, >=0 si OK
  959. */
  960. function DDLCreateUser($dolibarr_main_db_host,$dolibarr_main_db_user,$dolibarr_main_db_pass,$dolibarr_main_db_name)
  961. {
  962. $sql = "create user \"".addslashes($dolibarr_main_db_user)."\" with password '".addslashes($dolibarr_main_db_pass)."'";
  963. dol_syslog("pgsql.lib::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log
  964. $resql=$this->query($sql);
  965. if (! $resql)
  966. {
  967. return -1;
  968. }
  969. return 1;
  970. }
  971. /**
  972. * Decrit une table dans une database
  973. *
  974. * @param table Nom de la table
  975. * @param field Optionnel : Nom du champ si l'on veut la desc d'un champ
  976. * @return resource
  977. */
  978. function DDLDescTable($table,$field="")
  979. {
  980. $sql ="SELECT attname FROM pg_attribute, pg_type WHERE typname = '".$table."' AND attrelid = typrelid";
  981. $sql.=" AND attname NOT IN ('cmin', 'cmax', 'ctid', 'oid', 'tableoid', 'xmin', 'xmax')";
  982. if ($field) $sql.= " AND attname = '".$field."'";
  983. dol_syslog($sql,LOG_DEBUG);
  984. $this->results = $this->query($sql);
  985. return $this->results;
  986. }
  987. /**
  988. * Insert a new field in table
  989. *
  990. * @param table Nom de la table
  991. * @param field_name Nom du champ a inserer
  992. * @param field_desc Tableau associatif de description du champ a inserer[nom du parametre][valeur du parametre]
  993. * @param field_position Optionnel ex.: "after champtruc"
  994. * @return int <0 si KO, >0 si OK
  995. */
  996. function DDLAddField($table,$field_name,$field_desc,$field_position="")
  997. {
  998. // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra
  999. // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment');
  1000. $sql= "ALTER TABLE ".$table." ADD ".$field_name." ";
  1001. $sql .= $field_desc['type'];
  1002. if ($field_desc['type'] != 'int' && preg_match("/^[^\s]/i",$field_desc['value']))
  1003. $sql .= "(".$field_desc['value'].")";
  1004. if (preg_match("/^[^\s]/i",$field_desc['attribute']))
  1005. $sql .= " ".$field_desc['attribute'];
  1006. if (preg_match("/^[^\s]/i",$field_desc['null']))
  1007. $sql .= " ".$field_desc['null'];
  1008. if (preg_match("/^[^\s]/i",$field_desc['default']))
  1009. if (preg_match("/null/i",$field_desc['default']))
  1010. $sql .= " default ".$field_desc['default'];
  1011. else
  1012. $sql .= " default '".$field_desc['default']."'";
  1013. if (preg_match("/^[^\s]/i",$field_desc['extra']))
  1014. $sql .= " ".$field_desc['extra'];
  1015. $sql .= " ".$field_position;
  1016. dol_syslog($sql,LOG_DEBUG);
  1017. if(! $this -> query($sql))
  1018. return -1;
  1019. else
  1020. return 1;
  1021. }
  1022. /**
  1023. * Update format of a field into a table
  1024. *
  1025. * @param table Name of table
  1026. * @param field_name Name of field to modify
  1027. * @param field_desc Array with description of field format
  1028. * @return int <0 if KO, >0 if OK
  1029. */
  1030. function DDLUpdateField($table,$field_name,$field_desc)
  1031. {
  1032. $sql = "ALTER TABLE ".$table;
  1033. $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type'];
  1034. if ($field_desc['type'] == 'int' || $field_desc['type'] == 'varchar') $sql.="(".$field_desc['value'].")";
  1035. dol_syslog($sql,LOG_DEBUG);
  1036. if (! $this->query($sql))
  1037. return -1;
  1038. else
  1039. return 1;
  1040. }
  1041. /**
  1042. * Drop a field in table
  1043. *
  1044. * @param table Nom de la table
  1045. * @param field_name Nom du champ a inserer
  1046. * @return int <0 si KO, >0 si OK
  1047. */
  1048. function DDLDropField($table,$field_name)
  1049. {
  1050. $sql= "ALTER TABLE ".$table." DROP COLUMN `".$field_name."`";
  1051. dol_syslog($sql,LOG_DEBUG);
  1052. if (! $this->query($sql))
  1053. {
  1054. $this->error=$this->lasterror();
  1055. return -1;
  1056. }
  1057. else return 1;
  1058. }
  1059. /**
  1060. * Return charset used to store data in database
  1061. *
  1062. * @return string Charset
  1063. */
  1064. function getDefaultCharacterSetDatabase()
  1065. {
  1066. $resql=$this->query('SHOW SERVER_ENCODING');
  1067. $liste=$this->fetch_array($resql);
  1068. return $liste['server_encoding'];
  1069. }
  1070. /**
  1071. * Return list of available charset that can be used to store data in database
  1072. *
  1073. * @return array List of Charset
  1074. */
  1075. function getListOfCharacterSet()
  1076. {
  1077. $resql=$this->query('SHOW SERVER_ENCODING');
  1078. $liste = array();
  1079. if ($resql)
  1080. {
  1081. $i = 0;
  1082. while ($obj = $this->fetch_object($resql) )
  1083. {
  1084. $liste[$i]['charset'] = $obj->server_encoding;
  1085. $liste[$i]['description'] = 'Default database charset';
  1086. $i++;
  1087. }
  1088. $this->free($resql);
  1089. } else {
  1090. return null;
  1091. }
  1092. return $liste;
  1093. }
  1094. /**
  1095. * Return collation used in database
  1096. *
  1097. * @return string Collation value
  1098. */
  1099. function getDefaultCollationDatabase()
  1100. {
  1101. $resql=$this->query('SHOW LC_COLLATE');
  1102. $liste=$this->fetch_array($resql);
  1103. return $liste['lc_collate'];
  1104. }
  1105. /**
  1106. * Return list of available collation that can be used for database
  1107. *
  1108. * @return array Liste of Collation
  1109. */
  1110. function getListOfCollation()
  1111. {
  1112. $resql=$this->query('SHOW LC_COLLATE');
  1113. $liste = array();
  1114. if ($resql)
  1115. {
  1116. $i = 0;
  1117. while ($obj = $this->fetch_object($resql) )
  1118. {
  1119. $liste[$i]['collation'] = $obj->lc_collate;
  1120. $i++;
  1121. }
  1122. $this->free($resql);
  1123. } else {
  1124. return null;
  1125. }
  1126. return $liste;
  1127. }
  1128. /**
  1129. * Return full path of dump program
  1130. *
  1131. * @return string Full path of dump program
  1132. */
  1133. function getPathOfDump()
  1134. {
  1135. $fullpathofdump='/pathtopgdump/pg_dump';
  1136. if (file_exists('/usr/bin/pg_dump'))
  1137. {
  1138. $fullpathofdump='/usr/bin/pg_dump';
  1139. }
  1140. else
  1141. {
  1142. // TODO L'utilisateur de la base doit etre un superadmin pour lancer cette commande
  1143. $resql=$this->query('SHOW data_directory');
  1144. if ($resql)
  1145. {
  1146. $liste=$this->fetch_array($resql);
  1147. $basedir=$liste['data_directory'];
  1148. $fullpathofdump=preg_replace('/data$/','bin',$basedir).'/pg_dump';
  1149. }
  1150. }
  1151. return $fullpathofdump;
  1152. }
  1153. /**
  1154. * Return full path of restore program
  1155. *
  1156. * @return string Full path of restore program
  1157. */
  1158. function getPathOfRestore()
  1159. {
  1160. $fullpathofdump='/pathtopgrestore/pg_restore';
  1161. if (file_exists('/usr/bin/pg_restore'))
  1162. {
  1163. $fullpathofdump='/usr/bin/pg_restore';
  1164. }
  1165. else
  1166. {
  1167. // TODO L'utilisateur de la base doit etre un superadmin pour lancer cette commande
  1168. $resql=$this->query('SHOW data_directory');
  1169. if ($resql)
  1170. {
  1171. $liste=$this->fetch_array($resql);
  1172. $basedir=$liste['data_directory'];
  1173. $fullpathofdump=preg_replace('/data$/','bin',$basedir).'/pg_restore';
  1174. }
  1175. }
  1176. return $fullpathofdump;
  1177. }
  1178. /**
  1179. * Return value of server parameters
  1180. *
  1181. * @param filter Filter list on a particular value
  1182. * @return string Value for parameter
  1183. */
  1184. function getServerParametersValues($filter='')
  1185. {
  1186. $result=array();
  1187. $resql='select name,setting from pg_settings';
  1188. if ($filter) $resql.=" WHERE name = '".addslashes($filter)."'";
  1189. $resql=$this->query($resql);
  1190. if ($resql)
  1191. {
  1192. $obj=$this->fetch_object($resql);
  1193. $result[$obj->name]=$obj->setting;
  1194. }
  1195. return $result;
  1196. }
  1197. }
  1198. ?>