noalyss  Version-6.9.1.8
 All Data Structures Namespaces Files Functions Variables Pages
class_database.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of NOALYSS.
5  *
6  * NOALYSS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * NOALYSS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with NOALYSS; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 // Copyright Author Dany De Bontridder danydb@aevalys.eu
22 
23 /**
24  * \file
25  * \brief contains the class for connecting to a postgresql database
26  */
27 require_once NOALYSS_INCLUDE.'/constant.php';
28 require_once NOALYSS_INCLUDE.'/lib/ac_common.php';
29 
30 /**
31  * \brief
32  * This class allow you to connect to the postgresql database, execute sql, retrieve data
33  *
34  */
35 
36 class Database
37 {
38 
39  private $db; /**< database connection */
40  private $ret; /**< return value */
41  private $is_open; /*!< true is connected */
42  /**\brief constructor
43  * \param $p_database_id is the id of the dossier, or the modele following the
44  * p_type if = 0 then connect to the repository
45  * \param $p_type is 'DOS' (defaut) for dossier or 'MOD'
46  */
47 
48  function __construct($p_database_id=0, $p_type='dos')
49  {
50  if (IsNumber($p_database_id)==false||strlen($p_database_id)>10)
51  die("-->Dossier invalide [$p_database_id]");
52  $noalyss_user=(defined("noalyss_user"))?noalyss_user:phpcompta_user;
53  $password=(defined("noalyss_password"))?noalyss_password:phpcompta_password;
54  $port=(defined("noalyss_psql_port"))?noalyss_psql_port:phpcompta_psql_port;
55  $host=(!defined("noalyss_psql_host") )?'127.0.0.1':noalyss_psql_host;
56  if (defined("MULTI")&&MULTI=="0")
57  {
58  $l_dossier=dbname;
59  }
60  else
61  {
62 
63  if ($p_database_id==0)
64  { /* connect to the repository */
65  $l_dossier=sprintf("%saccount_repository", strtolower(domaine));
66  }
67  else if ($p_type=='dos')
68  { /* connect to a folder (dossier) */
69  $l_dossier=sprintf("%sdossier%d", strtolower(domaine), $p_database_id);
70  }
71  else if ($p_type=='mod')
72  { /* connect to a template (modele) */
73  $l_dossier=sprintf("%smod%d", strtolower(domaine), $p_database_id);
74  }
75  else if ($p_type=='template')
76  {
77  $l_dossier='template1';
78  }
79  else
80  {
81  throw new Exception('Connection invalide');
82  }
83  }
84 
85  ob_start();
86  $a=pg_connect("dbname=$l_dossier host='$host' user='$noalyss_user'
87  password='$password' port=$port");
88 
89  if ($a==false)
90  {
91  if (DEBUG)
92  {
93  ob_end_clean();
94  echo '<h2 class="error">Impossible de se connecter &agrave; postgreSql !</h2>';
95  echo '<p>';
96  echo "Vos param&egrave;tres sont incorrectes : <br>";
97  echo "<br>";
98  echo "base de donn&eacute;e : $l_dossier<br>";
99  echo "Domaine : ".domaine."<br>";
100  echo "Port $port <br>";
101  echo "Utilisateur : $noalyss_user <br>";
102  echo '</p>';
103 
104  die("Connection impossible : v&eacute;rifiez vos param&egrave;tres de base
105  de donn&eacute;es");
106  }
107  else
108  {
109  echo '<h2 class="error">Erreur de connexion !</h2>';
110  $this->is_open=false;
111  return;
112  }
113  }
114  $this->db=$a;
115  $this->is_open=TRUE;
116  if ($this->exist_schema('comptaproc')){
117  pg_exec($this->db, 'set search_path to public,comptaproc,pg_catalog;');
118  }
119  pg_exec($this->db, 'set DateStyle to ISO, MDY;');
120  ob_end_clean();
121  }
122  /**
123  * Connect to a database return an connx to db or false if it fails
124  *
125  * @param string $p_user Username
126  * @param type $p_password User's password
127  * @param $p_dbname name of the database to connect
128  * @param type $p_host Host of DB
129  * @param type $p_port Port of DB
130  */
131  static function connect($p_user,$p_password,$p_dbname,$p_host,$p_port) {
132  $a=pg_connect("dbname=$p_dbname host='$p_host' user='$p_user'
133  password='$p_password' port=$p_port");
134  return $a;
135  }
136  public function verify()
137  {
138  // Verify that the elt we want to add is correct
139  }
140 
141  function set_encoding($p_charset)
142  {
143  pg_set_client_encoding($this->db, $p_charset);
144  }
145  function get_encoding()
146  {
147  return pg_client_encoding($this->db);
148  }
149 
150 
151  /**
152  * \brief send a sql string to the database
153  * \param $p_string sql string
154  * \param $p_array array for the SQL string (see pg_query_params)
155  * \return the result of the query, a resource or false if an
156  * error occured
157  */
158 
159  function exec_sql($p_string, $p_array=null)
160  {
161  try
162  {
163  if ( ! $this->is_open ) throw new Exception(' Database is closed');
164  $this->sql=$p_string;
165  $this->array=$p_array;
166 
167  if ($p_array==null)
168  {
169  if (!DEBUG)
170  $this->ret=pg_query($this->db, $p_string);
171  else
172  $this->ret=@pg_query($this->db, $p_string);
173  }
174  else
175  {
176  $a=is_array($p_array);
177  if (!is_array($p_array))
178  {
179  throw new Exception("Erreur : exec_sql attend un array");
180  }
181  if (!DEBUG)
182  $this->ret=pg_query_params($this->db, $p_string, $p_array);
183  else
184  $this->ret=@pg_query_params($this->db, $p_string, $p_array);
185  }
186  if (!$this->ret)
187  {
188  $str_error=pg_last_error($this->db).pg_result_error($this->ret);
189  throw new Exception(" SQL ERROR $p_string ".$str_error, 1);
190  }
191  }
192  catch (Exception $a)
193  {
194  if (DEBUG)
195  {
196  print_r($p_string);
197  print_r($p_array);
198  echo $a->getMessage();
199  echo $a->getTrace();
200  echo $a->getTraceAsString();
201  echo pg_last_error($this->db);
202  }
203  error_log($a->getTraceAsString());
204  $this->rollback();
205 
206  throw ($a);
207  }
208 
209  return $this->ret;
210  }
211 
212  /**
213  * \brief Count the number of row returned by a sql statement
214  *
215  * \param $p_sql sql string
216  * \param $p_array if not null we use the safer pg_query_params
217  */
218 
219  function count_sql($p_sql, $p_array=null)
220  {
221  $r_sql=$this->exec_sql($p_sql, $p_array);
222  return pg_NumRows($r_sql);
223  }
224 
225  /**
226  * \brief get the current sequence value
227  */
228 
229  function get_current_seq($p_seq)
230  {
231  $Res=$this->get_value("select currval('$p_seq') as seq");
232  return $Res;
233  }
234 
235  /**
236  * \brief get the next sequence value
237  */
238 
239  function get_next_seq($p_seq)
240  {
241  $Res=$this->exec_sql("select nextval('$p_seq') as seq");
242  $seq=pg_fetch_array($Res, 0);
243  return $seq['seq'];
244  }
245 
246  /**
247  * @brief : start a transaction
248  *
249  */
250  function start()
251  {
252  $Res=$this->exec_sql("start transaction");
253  }
254 
255  /**
256  * Commit the transaction
257  *
258  */
259  function commit()
260  {
261  if ( ! $this->is_open) return;
262  $Res=$this->exec_sql("commit");
263  }
264 
265  /**
266  * rollback the current transaction
267  */
268  function rollback()
269  {
270  if ( ! $this->is_open) return;
271  $Res=$this->exec_sql("rollback");
272  }
273 
274  /**
275  * @brief alter the sequence value
276  * @param $p_name name of the sequence
277  * @param $min the start value of the sequence
278  */
279  function alter_seq($p_name, $min)
280  {
281  if ($min<1)
282  $min=1;
283  $Res=$this->exec_sql("alter sequence $p_name restart $min");
284  }
285 
286  /**
287  * \brief Execute a sql script
288  * \param $script script name
289  */
290 
292  {
293 
294  if (!DEBUG)
295  ob_start();
296  $hf=fopen($script, 'r');
297  if ($hf==false)
298  {
299  throw new Exception ( 'Ne peut ouvrir '.$script);
300  }
301  $sql="";
302  $flag_function=false;
303  while (!feof($hf))
304  {
305  $buffer=fgets($hf);
306  $buffer=str_replace("$", "\$", $buffer);
307  print $buffer."<br>";
308  // comment are not execute
309  if (substr($buffer, 0, 2)=="--")
310  {
311  //echo "comment $buffer";
312  continue;
313  }
314  // Blank Lines Are Skipped
315  If (Strlen($buffer)==0)
316  {
317  //echo "Blank $buffer";
318  Continue;
319  }
320  if (strpos(strtolower($buffer), "create function")===0)
321  {
322  echo "found a function";
323  $flag_function=true;
324  $sql=$buffer;
325  continue;
326  }
327  if (strpos(strtolower($buffer), "create or replace function")===0)
328  {
329  echo "found a function";
330  $flag_function=true;
331  $sql=$buffer;
332  continue;
333  }
334  // No semi colon -> multiline command
335  if ($flag_function==false&&strpos($buffer, ';')==false)
336  {
337  $sql.=$buffer;
338  continue;
339  }
340  if ($flag_function)
341  {
342  if (strpos(strtolower($buffer), "language plpgsql")===false&&
343  strpos(strtolower($buffer), "language 'plpgsql'")===false)
344  {
345  $sql.=$buffer;
346  continue;
347  }
348  }
349  else
350  {
351  // cut the semi colon
352  $buffer=str_replace(';', '', $buffer);
353  }
354  $sql.=$buffer;
355  if ($this->exec_sql($sql)==false)
356  {
357  $this->rollback();
358  if (!DEBUG)
359  ob_end_clean();
360  print "ERROR : $sql";
361  throw new Exception("ERROR : $sql");
362  }
363  $sql="";
364  $flag_function=false;
365  print "<hr>";
366  } // while (feof)
367  fclose($hf);
368  if (!DEBUG)
369  ob_end_clean();
370  }
371 
372  /**
373  * \brief Get version of a database, the content of the
374  * table version
375  *
376  * \return version number
377  *
378  */
379 
380  function get_version()
381  {
382  $Res=$this->get_value("select val from version");
383  return $Res;
384  }
385 
386  /**
387  * @brief fetch the $p_indice array from the last query
388  * @param $p_indice index
389  *
390  */
391  function fetch($p_indice)
392  {
393  if ($this->ret==false)
394  throw new Exception('this->ret is empty');
395  return pg_fetch_array($this->ret, $p_indice);
396  }
397 
398  /**
399  *
400  * @brief return the number of rows found by the last query, or the number
401  * of rows from $p_ret
402  * @param $p_ret is the result of a query, the default value is null, in that case
403  * it is related to the last query
404  * @note synomym for count()
405  */
406 
407  function size($p_ret=null)
408  {
409  if ($p_ret==null)
410  return pg_NumRows($this->ret);
411  else
412  return pg_NumRows($p_ret);
413  }
414 
415  /**
416  * @brief synomym for size()
417  */
418 
419  function count($p_ret=null)
420  {
421  return $this->size($p_ret);
422  }
423 
424  /**
425  * \brief loop to apply all the path to a folder or
426  * a template
427  * \param $p_name database name
428  *
429  */
430 
431  function apply_patch($p_name)
432  {
433  if ( ! $this->exist_table('version')) {
434  echo _('Base de donnée vide');
435  return;
436  }
437  $MaxVersion=DBVERSION-1;
438  $succeed="<span style=\"font-size:18px;color:green\">&#x2713;</span>";
439  echo '<ul style="list-type-style:square">';
440  for ($i=4; $i<=$MaxVersion; $i++)
441  {
442  $to=$i+1;
443 
444  if ($this->get_version()<=$i)
445  {
446  if ($this->get_version()==97)
447  {
448  if ($this->exist_schema("amortissement"))
449  {
450  $this->exec_sql('ALTER TABLE amortissement.amortissement_histo
451  ADD CONSTRAINT internal_fk FOREIGN KEY (jr_internal) REFERENCES jrn (jr_internal)
452  ON UPDATE CASCADE ON DELETE SET NULL');
453  }
454  }
455  echo "<li>Patching ".$p_name.
456  " from the version ".$this->get_version()." to $to ";
457 
458  $this->execute_script (NOALYSS_INCLUDE.'/sql/patch/upgrade'.$i.'.sql');
459  echo $succeed;
460 
461  if (!DEBUG)
462  ob_start();
463  // specific for version 4
464  if ($i==4)
465  {
466  $sql="select jrn_def_id from jrn_def ";
467  $Res=$this->exec_sql($sql);
468  $Max=$this->size();
469  for ($seq=0; $seq<$Max; $seq++)
470  {
471  $row=pg_fetch_array($Res, $seq);
472  $sql=sprintf("create sequence s_jrn_%d", $row['jrn_def_id']);
473  $this->exec_sql($sql);
474  }
475  }
476  // specific to version 7
477  if ($i==7)
478  {
479  // now we use sequence instead of computing a max
480  //
481  $Res2=$this->exec_sql('select coalesce(max(jr_grpt_id),1) as l from jrn');
482  $Max2=pg_NumRows($Res2);
483  if ($Max2==1)
484  {
485  $Row=pg_fetch_array($Res2, 0);
486  var_dump($Row);
487  $M=$Row['l'];
488  $this->exec_sql("select setval('s_grpt',$M,true)");
489  }
490  }
491  // specific to version 17
492  if ($i==17)
493  {
494  $this->execute_script(NOALYSS_INCLUDE.'/sql/patch/upgrade17.sql');
495  $max=$this->get_value('select last_value from s_jnt_fic_att_value');
496  $this->alter_seq($p_cn, 's_jnt_fic_att_value', $max+1);
497  } // version
498  // reset sequence in the modele
499  //--
500  if ($i==30&&$p_name=="mod")
501  {
502  $a_seq=array('s_jrn', 's_jrn_op', 's_centralized',
503  's_stock_goods', 'c_order', 's_central');
504  foreach ($a_seq as $seq)
505  {
506  $sql=sprintf("select setval('%s',1,false)", $seq);
507  $Res=$this->exec_sql($sql);
508  }
509  $sql="select jrn_def_id from jrn_def ";
510  $Res=$this->exec_sql($sql);
511  $Max=pg_NumRows($Res);
512  for ($seq=0; $seq<$Max; $seq++)
513  {
514  $row=pg_fetch_array($Res, $seq);
515  $sql=sprintf("select setval('s_jrn_%d',1,false)", $row['jrn_def_id']);
516  $this->exec_sql($sql);
517  }
518  }
519  if ($i==36)
520  {
521  /* check the country and apply the path */
522  $res=$this->exec_sql("select pr_value from parameter where pr_id='MY_COUNTRY'");
523  $country=pg_fetch_result($res, 0, 0);
524  $this->execute_script(NOALYSS_INCLUDE."/sql/patch/upgrade36.".$country.".sql");
525  $this->exec_sql('update tmp_pcmn set pcm_type=find_pcm_type(pcm_val)');
526  }
527  if ($i==59)
528  {
529  $res=$this->exec_sql("select pr_value from parameter where pr_id='MY_COUNTRY'");
530  $country=pg_fetch_result($res, 0, 0);
531  if ($country=='BE')
532  $this->exec_sql("insert into parm_code values ('SUPPLIER',440,'Poste par défaut pour les fournisseurs')");
533  if ($country=='FR')
534  $this->exec_sql("insert into parm_code values ('SUPPLIER',400,'Poste par défaut pour les fournisseurs')");
535  }
536  if ($i==61)
537  {
538  $country=$this->get_value("select pr_value from parameter where pr_id='MY_COUNTRY'");
539  $this->execute_script(NOALYSS_INCLUDE."/sql/patch/upgrade61.".$country.".sql");
540  }
541 
542  if (!DEBUG)
543  ob_end_clean();
544  }
545  }
546  echo '</ul>';
547  }
548 
549  /**
550  *
551  * \brief return the value of the sql, the sql will return only one value
552  * with the value
553  * \param $p_sql the sql stmt example :select s_value from
554  document_state where s_id=2
555  * \param $p_array if array is not null we use the ExecSqlParm (safer)
556  * \see exec_sql
557  * \note print a warning if several value are found, if only the first value is needed
558  * consider using a LIMIT clause
559  * \return only the first value or an empty string if nothing is found
560  */
561 
562  function get_value($p_sql, $p_array=null)
563  {
564  $this->ret=$this->exec_sql($p_sql, $p_array);
565  $r=pg_NumRows($this->ret);
566  if ($r==0)
567  return "";
568  if ($r>1)
569  {
570  $array=pg_fetch_all($this->ret);
571  throw new Exception("Attention $p_sql retourne ".pg_NumRows($this->ret)." valeurs ".
572  var_export($p_array, true)." values=".var_export($array, true));
573  }
574  $r=pg_fetch_row($this->ret, 0);
575  return $r[0];
576  }
577  /**
578  * @brief return the number of rows affected by the previous query
579  */
580  function get_affected()
581  {
582  return Database::num_row($this->ret);
583  }
584 
585  /**
586  * \brief purpose return the result of a sql statment
587  * in a array
588  * \param $p_sql sql query
589  * \param $p_array if not null we use ExecSqlParam
590  * \return false if nothing is found
591  */
592 
593  function get_array($p_sql, $p_array=null)
594  {
595  $r=$this->exec_sql($p_sql, $p_array);
596 
597  if (pg_NumRows($r)==0)
598  return array();
599  $array=pg_fetch_all($r);
600  return $array;
601  }
602  /**
603  * Returns only one row from a query
604  * @param string $p_sql
605  * @param array $p_array
606  * @return array , idx = column of the table or null if nothing is found
607  * @throws Exception if too many rows are found code 100
608  */
609  function get_row($p_sql,$p_array=NULL) {
610  $array=$this->get_array($p_sql,$p_array);
611  if (empty($array) ) return null;
612  if (count($array)==1) return $array[0];
613  throw new Exception("Database:get_row retourne trop de lignes",100);
614  }
615  /**
616  * @brief Create a sequence
617  * @param string $p_name Sequence Name
618  * @param int $min starting value
619  */
620  function create_sequence($p_name, $min=1)
621  {
622  if ($min<1)
623  $min=1;
624  $sql="create sequence ".$p_name." minvalue $min";
625  $this->exec_sql($sql);
626  }
627 
628  /**
629  * \brief test if a sequence exist */
630  /* \return true if the seq. exist otherwise false
631  */
632 
633  function exist_sequence($p_name)
634  {
635  $r=$this->count_sql("select relname from pg_class where relname=lower($1)", array($p_name));
636  if ($r==0)
637  return false;
638  return true;
639  }
640 
641  /**
642  * \brief test if a table exist
643  * \param $p_name table name
644  * \param $schema name of the schema default public
645  * \return true if a table exist otherwise false
646  */
647 
648  function exist_table($p_name, $p_schema='public')
649  {
650  $r=$this->count_sql("select table_name from information_schema.tables where table_schema=$1 and table_name=lower($2)", array($p_schema, $p_name));
651  if ($r==0)
652  return false;
653  return true;
654  }
655 
656  /**
657  * Check if a column exists in a table
658  * @param $col : column name
659  * @param $table :table name
660  * @param $schema :schema name, default public
661  * @return true or false
662  */
663  function exist_column($col, $table, $schema)
664  {
665  $r=$this->get_value('select count(*) from information_schema.columns where table_name=lower($1) and column_name=lower($2) and table_schema=lower($3)', array($col, $table, $schema));
666  if ($r>0)
667  return true;
668  return false;
669  }
670 
671  /**
672  * return the name of the database with the domain name
673  * @param $p_id of the folder WITHOUT the domain name
674  * @param $p_type dos for folder mod for template
675  * @return formatted name
676  */
678  {
679  switch ($p_type)
680  {
681  case 'dos':
682  $sys_name=sprintf("%sdossier%d", strtolower(domaine), $p_id);
683  break;
684  case 'mod':
685  $sys_name=sprintf("%smod%d", strtolower(domaine), $p_id);
686  break;
687  default:
688  echo_error(__FILE__." format_name invalid type ".$p_type, __LINE__);
689  throw new Exception(__FILE__." format_name invalid type ".$p_type. __LINE__);
690  }
691  return $sys_name;
692  }
693 
694  /**
695  * Count the database name in a system view
696  * @param $p_name string database name
697  * @return number of database found (normally 0 or 1)
698  */
699  function exist_database($p_name)
700  {
701  $database_exist=$this->get_value('select count(*)
702  from pg_catalog.pg_database where datname = lower($1)', array($p_name));
703  return $database_exist;
704  }
705 
706  /**
707  * @brief check if the large object exists
708  * @param $p_oid of the large object
709  * @return return true if the large obj exist or false if not
710  */
711  function exist_blob($p_oid)
712  {
713  $r=$this->get_value('select count(*) from pg_largeobject_metadata where oid=$1'
714  , array($p_oid));
715  if ($r>0)
716  return true;
717  else
718  return false;
719  }
720 
721  /*
722  * !\brief test if a view exist
723  * \return true if the view. exist otherwise false
724  */
725 
726  function exist_view($p_name)
727  {
728  $r=$this->count_sql("select viewname from pg_views where viewname=lower($1)", array($p_name));
729  if ($r==0)
730  return false;
731  return true;
732  }
733 
734  /*
735  * !\brief test if a schema exists
736  * \return true if the schemas exists otherwise false
737  */
738 
739  function exist_schema($p_name)
740  {
741  $r=$this->count_sql("select nspname from pg_namespace where nspname=lower($1)", array($p_name));
742  if ($r==0)
743  return false;
744  return true;
745  }
746 
747  /**
748  * \brief create a string containing the value separated by comma
749  * for use in a SQL in statement
750  * \return the string or empty if nothing is found
751  * \see fid_card.php
752  */
753 
754  function make_list($sql, $p_array=null)
755  {
756  if ($p_array==null)
757  {
758  $aArray=$this->get_array($sql);
759  }
760  else
761  {
762  $aArray=$this->get_array($sql, $p_array);
763  }
764  if (empty($aArray))
765  return "";
766  $aIdx=array_keys($aArray[0]);
767  $idx=$aIdx[0];
768  $ret="";
769  $f="";
770  for ($i=0; $i<count($aArray); $i++)
771  {
772  $row=$aArray[$i];
773  $ret.=$f.$aArray[$i][$idx];
774  $f=',';
775  }
776  $ret=trim($ret, ',');
777  return $ret;
778  }
779 
780  /**
781  * \brief make a array with the sql.
782  *
783  * \param $p_sql sql statement, only the first two column will be returned in
784  * an array. The first col. is the label and the second the value
785  * \param $p_null if the array start with a null value
786  * \param $p_array is the array with the bind value
787  * \note this function is used with ISelect when it is needed to have a list of
788  * options.
789  * \return: a double array like
790  \verbatim
791  Array
792  (
793  [0] => Array
794  (
795  [value] => 1
796  [label] => Marchandise A
797  )
798 
799  [1] => Array
800  (
801  [value] => 2
802  [label] => Marchandise B
803  )
804 
805  [2] => Array
806  (
807  [value] => 3
808  [label] => Marchandise C
809  )
810  )
811  \endverbatim
812  * \see ISelect
813  */
814 
815  function make_array($p_sql, $p_null=0,$p_array=null)
816  {
817  $a=$this->exec_sql($p_sql,$p_array);
818  $max=pg_NumRows($a);
819  if ($max==0&&$p_null==0)
820  return null;
821  for ($i=0; $i<$max; $i++)
822  {
823  $row=pg_fetch_row($a);
824  $r[$i]['value']=$row[0];
825  $r[$i]['label']=h($row[1]);
826  }
827  // add a blank item ?
828  if ($p_null==1)
829  {
830  for ($i=$max; $i!=0; $i--)
831  {
832  $r[$i]['value']=$r[$i-1]['value'];
833  $r[$i]['label']=h($r[$i-1]['label']);
834  }
835  $r[0]['value']=-1;
836  $r[0]['label']=" ";
837  } // if ( $p_null == 1 )
838 
839  return $r;
840  }
841  /***
842  * \brief Save a "piece justificative" , the name must be pj
843  *
844  * \param $seq jr_grpt_id
845  * \return $oid of the lob file if success
846  * null if a error occurs
847  *
848  */
849  function save_receipt($seq)
850  {
851  $oid=$this->upload('pj');
852  if ($oid==false)
853  {
854  return false;
855  }
856  // Remove old document
857  $ret=$this->exec_sql("select jr_pj from jrn where jr_grpt_id=$seq");
858  if (pg_num_rows($ret)!=0)
859  {
860  $r=pg_fetch_array($ret, 0);
861  $old_oid=$r['jr_pj'];
862  if (strlen($old_oid)!=0)
863  pg_lo_unlink($cn, $old_oid);
864  }
865  // Load new document
866  $this->exec_sql("update jrn set jr_pj=$1 , jr_pj_name=$2,
867  jr_pj_type=$3 where jr_grpt_id=$4",
868  array($oid,$_FILES['pj']['name'] ,$_FILES['pj']['type'],$seq));
869  return $oid;
870  }
871  /***
872  * \brief Save a document into the database , it just puts the file in the database
873  * and returns the corresponding OID , the mimetype , size ... of the document
874  * must be set in the calling function.
875  *
876  * \param name of the variable in $_FILES
877  * \return $oid of the lob file if success
878  * false if a error occurs or if there is no file to upload
879  *
880  */
881 
882  function upload($p_name)
883  {
884  /* there is no file to upload */
885  if ($_FILES[$p_name]["error"]==UPLOAD_ERR_NO_FILE)
886  {
887  return false;
888  }
889 
890  $new_name=tempnam($_ENV['TMP'], $p_name);
891  if ($_FILES[$p_name]["error"]>0)
892  {
893  print_r($_FILES);
894  echo_error(__FILE__.":".__LINE__."Error: ".$_FILES[$p_name]["error"]);
895  return false;
896  }
897  if (strlen($_FILES[$p_name]['tmp_name'])!=0)
898  {
899  if (move_uploaded_file($_FILES[$p_name]['tmp_name'], $new_name))
900  {
901  // echo "Image saved";
902  $oid=pg_lo_import($this->db, $new_name);
903  if ($oid==false)
904  {
905  echo_error(__FILE__, __LINE__, "cannot upload document");
906  $this->rollback();
907  return false;
908  }
909  return $oid;
910  }
911  else
912  {
913  echo "<H1>Error</H1>";
914  $this->rollback();
915  return false;
916  }
917  }
918  return false;
919  }
920 
921  /**\brief wrapper for the function pg_NumRows
922  * \param $ret is the result of a exec_sql
923  * \return number of line affected
924  */
925 
926  static function num_row($ret)
927  {
928  return pg_NumRows($ret);
929  }
930 
931  /**\brief wrapper for the function pg_fetch_array
932  * \param $ret is the result of a pg_exec
933  * \param $p_indice is the index
934  * \return $array of column
935  */
936 
937  static function fetch_array($ret, $p_indice=0)
938  {
939  return pg_fetch_array($ret, $p_indice);
940  }
941 
942  /**\brief wrapper for the function pg_fetch_all
943  * \param $ret is the result of pg_exec (exec_sql)
944  * \return double array (row x col )
945  */
946 
947  static function fetch_all($ret)
948  {
949  return pg_fetch_all($ret);
950  }
951 
952  /**\brief wrapper for the function pg_fetch_all
953  * \param $ret is the result of pg_exec (exec_sql)
954  * \param $p_row is the indice of the row
955  * \param $p_col is the indice of the col
956  * \return a string or an integer
957  */
958 
959  static function fetch_result($ret, $p_row=0, $p_col=0)
960  {
961  return pg_fetch_result($ret, $p_row, $p_col);
962  }
963 
964  /**\brief wrapper for the function pg_fetch_row
965  * \param $ret is the result of pg_exec (exec_sql)
966  * \param $p_row is the indice of the row
967  * \return an array indexed from 0
968  */
969 
970  static function fetch_row($ret, $p_row)
971  {
972  return pg_fetch_row($ret, $p_row);
973  }
974 
975  /**\brief wrapper for the function pg_lo_unlink
976  * \param $p_oid is the of oid
977  * \return return the result of the operation
978  */
979 
980  function lo_unlink($p_oid)
981  {
982  if ( ! $this->exist_blob($p_oid)) return;
983  return pg_lo_unlink($this->db, $p_oid);
984  }
985 
986  /**\brief wrapper for the function pg_prepare
987  * \param $p_string string name for pg_prepare function
988  * \param $p_sql is the sql to prepare
989  * \return return the result of the operation
990  */
991 
992  function prepare($p_string, $p_sql)
993  {
994  return pg_prepare($this->db, $p_string, $p_sql);
995  }
996 
997  /**
998  * \brief wrapper for the function pg_execute
999  * \param $p_string string name of the stmt given in pg_prepare function
1000  * \param $p_array contains the variables
1001  * \note set this->ret to the return of pg_execute
1002  * \return return the result of the operation,
1003  */
1004 
1005  function execute($p_string, $p_array)
1006  {
1007  $this->ret=pg_execute($this->db, $p_string, $p_array);
1008  return $this->ret;
1009  }
1010 
1011  /**
1012  * \brief wrapper for the function pg_lo_export
1013  * \param $p_oid is the oid of the log
1014  * \param $tmp is the file
1015  * \return result of the operation
1016  */
1017 
1018  function lo_export($p_oid, $tmp)
1019  {
1020  return pg_lo_export($this->db, $p_oid, $tmp);
1021  }
1022 
1023  /**\brief wrapper for the function pg_lo_export
1024  * \param $p_oid is the filename
1025  * \param $tmp is the file
1026  * \return result of the operation
1027  */
1028 
1029  function lo_import($p_oid)
1030  {
1031  return pg_lo_import($this->db, $p_oid);
1032  }
1033 
1034  /**\brief wrapper for the function pg_escape_string
1035  * \param $p_string is the string to escape
1036  * \return escaped string
1037  */
1038 
1039  static function escape_string($p_string)
1040  {
1041  return pg_escape_string($p_string);
1042  }
1043 
1044  /**\brief wrapper for the function pg_close
1045  */
1046 
1047  function close()
1048  {
1049  if ( $this->is_open ) pg_close($this->db);
1050  $this->is_open=FALSE;
1051  }
1052 
1053  /**\brief
1054  * \param
1055  * \return
1056  * \note
1057  * \see
1058  */
1059 
1060  function __toString()
1061  {
1062  return "database ";
1063  }
1064 
1065  static function test_me()
1066  {
1067 
1068  }
1069 
1070  function status()
1071  {
1072  return pg_transaction_status($this->db);
1073  }
1074 
1075  /**
1076  * with the handle of a successull query, echo each row into CSV and
1077  * send it directly
1078  * @param type $ret handle to a query
1079  * @param type $aheader double array, each item of the array contains
1080  * a key type (num) and a key title
1081  */
1082  function query_to_csv($ret, $aheader)
1083  {
1084  $seq="";
1085  for ($i=0; $i<count($aheader); $i++)
1086  {
1087  echo $seq.'"'.$aheader[$i]['title'].'"';
1088  $seq=";";
1089  }
1090  printf("\n\r");
1091  // fetch all the rows
1092  for ($i=0; $i<Database::num_row($ret); $i++)
1093  {
1095  $sep2="";
1096  // for each rows, for each value
1097  for ($e=0; $e<count($row)/2; $e++)
1098  {
1099  switch ($aheader[$e]['type'])
1100  {
1101  case 'num':
1102  echo $sep2.nb($row[$e]);
1103  break;
1104  default:
1105  echo $sep2.'"'.$row[$e].'"';
1106  }
1107  $sep2=";";
1108  }
1109  printf("\n\r");
1110  }
1111  }
1112  /**
1113  * @brief Find all lob and remove those which are not used by any tables
1114  *
1115  */
1116  function clean_orphan_lob()
1117  {
1118  // find all columns of type lob
1119  $sql ="
1120  select table_schema,table_name,column_name
1121  from
1122  information_schema.columns
1123  where table_schema not in ('information_schema','pg_catalog')
1124  and data_type='oid'";
1125  $all_lob= "
1126  select oid,'N' as used from pg_largeobject_metadata
1127  ";
1128  $a_table= $this->get_array($sql);
1129  $a_lob = $this->get_array($all_lob);
1130  if ( $a_table == false || $a_lob == false ) return;
1131  // for each lob
1132  $nb_lob=count($a_lob);
1133  $nb_table=count($a_table);
1134  for ($i=0;$i < $nb_lob;$i++)
1135  {
1136  $lob=$a_lob[$i]['oid'];
1137  if ( $a_lob[$i]['used']=='Y') continue;
1138  for ($j=0;$j < $nb_table;$j++)
1139  {
1140  if ( $a_lob[$i]['used']=='Y') continue;
1141  $check = $this->get_value(" select count(*) from ".
1142  $a_table[$j]['table_schema'].".".$a_table[$j]['table_name'].
1143  " where ".
1144  $a_table[$j]['column_name']."=$1",array($lob));
1145  if ( $check != 0 )
1146  $a_lob[$i]['used']='Y';
1147 
1148  }
1149  }
1150  for ($i=0;$i < $nb_lob;$i++)
1151  {
1152  if ( $a_lob[$i]['used']=='Y') continue;
1153  $this->lo_unlink($a_lob[$i]['oid']);
1154  }
1155  }
1156 
1157 }
1158 
1159 /* test::test_me(); */
count_sql($p_sql, $p_array=null)
Count the number of row returned by a sql statement.
format_name($p_id, $p_type)
return the name of the database with the domain name
static fetch_all($ret)
wrapper for the function pg_fetch_all
execute($p_string, $p_array)
wrapper for the function pg_execute
exist_table($p_name, $p_schema='public')
test if a table exist
exist_sequence($p_name)
test if a sequence exist
get_affected()
return the number of rows affected by the previous query
static num_row($ret)
wrapper for the function pg_NumRows
lo_import($p_oid)
wrapper for the function pg_lo_export
size($p_ret=null)
return the number of rows found by the last query, or the number of rows from $p_ret ...
make_list($sql, $p_array=null)
create a string containing the value separated by comma for use in a SQL in statement ...
create_sequence($p_name, $min=1)
Create a sequence.
clean_orphan_lob()
Find all lob and remove those which are not used by any tables.
start()
: start a transaction
const DBVERSION(!defined("SYSINFO_DISPLAY"))
Definition: constant.php:111
fetch($p_indice)
fetch the $p_indice array from the last query
query_to_csv($ret, $aheader)
with the handle of a successull query, echo each row into CSV and send it directly ...
$idx
close()
wrapper for the function pg_close
static escape_string($p_string)
wrapper for the function pg_escape_string
$ret
return value
exec_sql($p_string, $p_array=null)
send a sql string to the database
exist_schema($p_name)
switch($ss_action) $f
execute_script($script)
Execute a sql script.
static fetch_array($ret, $p_indice=0)
wrapper for the function pg_fetch_array
echo_error($p_log, $p_line="", $p_message="")
log error into the /tmp/noalyss_error.log it doesn't work on windows
Definition: ac_common.php:153
get_version()
Get version of a database, the content of the table version.
commit()
Commit the transaction.
apply_patch($p_name)
loop to apply all the path to a folder or a template
get_current_seq($p_seq)
get the current sequence value
set_encoding($p_charset)
lo_export($p_oid, $tmp)
wrapper for the function pg_lo_export
lo_unlink($p_oid)
wrapper for the function pg_lo_unlink
static fetch_row($ret, $p_row)
wrapper for the function pg_fetch_row
function trim(s)
remove trailing and heading space
Definition: scripts.js:95
get_next_seq($p_seq)
get the next sequence value
$db
database connection
save_receipt($seq)
$to
Definition: balance.inc.php:77
rollback()
rollback the current transaction
h($p_string)
to protect again bad characters which can lead to a cross scripting attack the string to be diplayed ...
Definition: ac_common.php:38
This class allow you to connect to the postgresql database, execute sql, retrieve data...
static fetch_result($ret, $p_row=0, $p_col=0)
wrapper for the function pg_fetch_all
$check
get_row($p_sql, $p_array=NULL)
Returns only one row from a query.
upload($p_name)
static connect($p_user, $p_password, $p_dbname, $p_host, $p_port)
Connect to a database return an connx to db or false if it fails.
$SecUser db
exist_column($col, $table, $schema)
Check if a column exists in a table.
static test_me()
__construct($p_database_id=0, $p_type='dos')
constructor
prepare($p_string, $p_sql)
wrapper for the function pg_prepare
make_array($p_sql, $p_null=0, $p_array=null)
make a array with the sql.
count($p_ret=null)
synomym for size()
alter_seq($p_name, $min)
alter the sequence value
exist_blob($p_oid)
check if the large object exists
get_value($p_sql, $p_array=null)
return the value of the sql, the sql will return only one value with the value
get_array($p_sql, $p_array=null)
purpose return the result of a sql statment in a array
exist_view($p_name)
exist_database($p_name)
Count the database name in a system view.