noalyss Version-10
NOALYSS : serveur de comptabilité et ERP (2002)
Loading...
Searching...
No Matches
database_core.class.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 */
27require_once NOALYSS_INCLUDE . '/constant.php';
28require_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 */
36{
37
38 protected $db;
39 /**< database connection */
40 protected $ret;
41 /**< return value */
42 protected $is_open; /*!< true is connected */
43 public $sql; //!< last SQL stmt executed
44 public $array;
45 protected $dbname; ///!< $dbname (string) Database name
46 protected $dbport;///!< $dbport (int) Database port
47 protected $dbhost;///!< $dbhost(string) Database host
48 protected $dbuser;///!< $dbuser(string) Database user
49 /***
50 * @brief Connect to a database return an connx to db or false if it fails
51 *
52 * @param string $p_user Username
53 * @param type $p_password User's password
54 * @param $p_dbname name of the database to connect
55 * @param type $p_host Host of DB
56 * @param type $p_port Port of DB
57 */
58
59 function __construct($p_user, $p_password, $p_dbname, $p_host, $p_port)
60 {
61 $this->db = @pg_connect("dbname=$p_dbname host='$p_host' user='$p_user'
62 password='$p_password' port=$p_port");
63 if ($this->db == false) {
64 if ( DEBUGNOALYSS > 0 ) {
65
66 echo '<h2 class="error">'._('Impossible de se connecter à postgreSql').'</h2>';
67 echo '<p>';
68 echo _("Vos paramètres sont incorrectes").": <br>";
69 echo "<br>";
70 printf (_("base de donnée = %s"), $p_dbname)."<br>";
71 printf (_("Port %s"),$p_port )."<br>";
72 printf ( _("Utilisateur : %s"),$p_user )."<br>";
73 echo '</p>';
74
75 die();
76 } else {
77 echo '<h2 class="error">' . _('Erreur de connexion !') . '</h2>';
78 $this->is_open = false;
79 throw new Exception(_('Erreur Connexion'));
80 }
81 }
82 $this->dbport=$p_port;
83 $this->dbname=$p_dbname;
84 $this->dbhost=$p_host;
85 $this->dbuser=$p_user;
86 $this->is_open = TRUE;
87 $this->sql="";
88
89 }
90 public function get_dbname() {
91 return $this->dbname;
92 }
93
94 public function get_dbport() {
95 return $this->dbport;
96 }
97
98 public function get_dbhost() {
99 return $this->dbhost;
100 }
101
102 public function get_dbuser() {
103 return $this->dbuser;
104 }
105
106 /**
107 * return the name of the current database
108 * @return false|string
109 */
110 public function get_name () {
111 return pg_dbname($this->db);
112 }
113
114 public function verify()
115 {
116 // Verify that the elt we want to add is correct
117 }
118
119 function set_encoding($p_charset)
120 {
121 pg_set_client_encoding($this->db, $p_charset);
122 }
123
124 function get_encoding()
125 {
126 return pg_client_encoding($this->db);
127 }
128
129
130 /**
131 * @return mixed
132 */
133 public function get_db()
134 {
135 return $this->db;
136 }
137
138 /**
139 * @param mixed $db
140 */
141 public function set_db($db)
142 {
143 $this->db = $db;
144 }
145
146 /**
147 * @return mixed
148 */
149 public function get_ret()
150 {
151 return $this->ret;
152 }
153
154 /**
155 * @param mixed $ret
156 */
157 public function set_ret($ret)
158 {
159 $this->ret = $ret;
160 }
161
162 /**
163 * @return mixed
164 */
165 public function get_is_open()
166 {
167 return $this->is_open;
168 }
169
170 /**
171 * @param mixed $is_open
172 */
173 public function set_is_open($is_open)
174 {
175 $this->is_open = $is_open;
176 }
177 /**
178 * last SQL stmt executed
179 * @param string $sql
180 */
181 public function get_sql()
182 {
183 return $this->sql;
184 }
185 /**
186 * last SQL stmt executed
187 * @param string $sql
188 */
189 public function set_sql($sql)
190 {
191 $this->sql=$sql;
192 return $this;
193 }
194
195 /**
196 * \brief send a sql string to the database
197 * \param $p_string sql string
198 * \param $p_array array for the SQL string (see pg_query_params)
199 * \return the result of the query, a resource or false if an
200 * error occured
201 */
202
203 function exec_sql($p_string, $p_array = null)
204 {
205 try {
206 if (!$this->is_open) throw new Exception(' Database is closed');
207 $this->sql = $p_string;
208 $this->array = $p_array;
209
210 if ($p_array == null) {
211 if ( DEBUGNOALYSS == 0 )
212 $this->ret = pg_query($this->db, $p_string);
213 else
214 $this->ret = @pg_query($this->db, $p_string);
215 } else {
216 $a = is_array($p_array);
217 if (!is_array($p_array)) {
218 throw new Exception(_("Erreur : exec_sql attend un array"));
219 }
220 if ( DEBUGNOALYSS == 0 )
221 $this->ret =@pg_query_params($this->db, $p_string, $p_array);
222 else
223 $this->ret = pg_query_params($this->db, $p_string, $p_array);
224 }
225 if ($this->ret == false) {
226 $str_error = pg_last_error($this->db) ;
227 throw new Exception(" SQL ERROR $p_string " . $str_error, 1);
228 }
229 } catch (Exception $a) {
230 if ( DEBUGNOALYSS > 0 ) {
231 print_r($p_string);
232 print_r($p_array);
233 echo $a->getMessage();
234 echo $a->getTraceAsString();
235 echo pg_last_error($this->db);
236 }
237 record_log($a);
238 record_log($p_string);
240 $this->rollback();
241
242 throw new \Exception("exec_sql fails",242,$a);
243 }
244
245 return $this->ret;
246 }
247
248 /**
249 * \brief Count the number of row returned by a sql statement
250 *
251 * \param $p_sql sql string
252 * \param $p_array if not null we use the safer pg_query_params
253 */
254
255 function count_sql($p_sql, $p_array = null)
256 {
257 $r_sql = $this->exec_sql($p_sql, $p_array);
258 return pg_num_rows($r_sql);
259 }
260
261 /**
262 * \brief get the current sequence value
263 */
264
265 function get_current_seq($p_seq)
266 {
267 $Res = $this->get_value("select currval('$p_seq') as seq");
268 return $Res;
269 }
270
271 /**
272 * \brief get the next sequence value
273 */
274
275 function get_next_seq($p_seq)
276 {
277 $Res = $this->exec_sql("select nextval('$p_seq') as seq");
278 $seq = pg_fetch_array($Res, 0);
279 return $seq['seq'];
280 }
281
282 /**
283 * @brief : start a transaction
284 *
285 */
286 function start()
287 {
288 $Res = $this->exec_sql("start transaction");
289 }
290
291 /**
292 * Commit the transaction
293 *
294 */
295 function commit()
296 {
297 if (!$this->is_open) return;
298 $Res = $this->exec_sql("commit");
299 }
300
301 /**
302 * rollback the current transaction
303 */
304 function rollback()
305 {
306 if (!$this->is_open) return;
307 $Res = $this->exec_sql("rollback");
308 }
309
310 /**
311 * @brief alter the sequence value
312 * @param $p_name name of the sequence
313 * @param $min the start value of the sequence
314 */
315 function alter_seq($p_name, $min)
316 {
317 if ($min < 1)
318 $min = 1;
319 $Res = $this->exec_sql("alter sequence $p_name restart $min");
320 }
321
322 /**
323 * \brief Execute a sql script
324 * \param $script script name
325 */
326
328 {
329
330 if ( DEBUGNOALYSS == 0 ) {
331 ob_start();
332 } else {
333 $debug = fopen("/tmp/debug_execute_script".uniqid().".log", "w+");
334 }
335 $hf = fopen($script, 'r');
336 if ($hf == false) {
337 throw new Exception ('Ne peut ouvrir ' . $script);
338 }
339 printf (" open %s <br>", $script);
340 $sql = "";
341 $flag_function = false;
342 while (!feof($hf)) {
343 $buffer = fgets($hf);
344 $buffer = str_replace('$BODY$', '$_$', $buffer);
345 print $buffer . "<br>";
346 // comment are not execute
347 if (substr($buffer, 0, 2) == "--") {
348 //echo "comment $buffer";
349 continue;
350 }
351 // Blank Lines Are Skipped
352 If (Strlen($buffer) == 0) {
353 //echo "Blank $buffer";
354 Continue;
355 }
356 if (strpos(strtolower($buffer), "create function") === 0) {
357 echo "found a function";
358 $flag_function = true;
359 $sql = $buffer;
360 continue;
361 }
362 if (strpos(strtolower($buffer), "create or replace function") === 0) {
363 echo "found a function";
364 $flag_function = true;
365 $sql = $buffer;
366 continue;
367 }
368 // No semi colon -> multiline command
369 if ($flag_function == false && strpos($buffer, ';') == false) {
370 $sql .= $buffer;
371 continue;
372 }
373 if ($flag_function) {
374 if (strpos(strtolower($buffer), "$$;") === false &&
375 strpos(strtolower($buffer), '$_$;') === false &&
376 strpos(strtolower($buffer), '$function$;') === false &&
377 strpos(strtolower($buffer), 'language plpgsql;') === false &&
378 strpos(strtolower($buffer), 'language plpgsql ;') === false
379 ) {
380 $sql .= $buffer;
381 continue;
382 }
383 } else {
384 // cut the semi colon
385 $buffer = str_replace(';', '', $buffer);
386 }
387 $sql .= $buffer;
388 if ( DEBUGNOALYSS > 0 ) fwrite($debug, $sql);
389 if ($this->exec_sql($sql) == false) {
390
391 $this->rollback();
392 if ( DEBUGNOALYSS == 0 )
393 ob_end_clean();
394 print "ERROR : $sql";
395 throw new Exception("ERROR : $sql");
396 }
397 $sql = "";
398 $flag_function = false;
399 print "<hr>";
400 } // while (feof)
401 fclose($hf);
402 if ( DEBUGNOALYSS == 0 )
403 ob_end_clean();
404 }
405
406
407 /**
408 * @brief fetch the $p_indice array from the last query
409 * @param $p_mode is PGSQL_ASSOC, PGSQL_BOTH or PGSQL_NUM (default PGSQL_ASSOC)
410 * @param $p_indice index
411 *
412 */
413 function fetch($p_indice,$p_mode= PGSQL_ASSOC)
414 {
415 if ($this->ret == false)
416 throw new Exception('this->ret is empty');
417 return pg_fetch_array($this->ret, $p_indice,$p_mode);
418 }
419
420 /**
421 *
422 * @brief return the number of rows found by the last query, or the number
423 * of rows from $p_ret
424 * @param $p_ret is the result of a query, the default value is null, in that case
425 * it is related to the last query
426 * @note synomym for count()
427 */
428
429 function size($p_ret = null)
430 {
431 if ($p_ret == null)
432 return pg_num_rows($this->ret);
433 else
434 return pg_num_rows($p_ret);
435 }
436
437 /**
438 * @brief synomym for size()
439 */
440
441 function count($p_ret = null)
442 {
443 return $this->size($p_ret);
444 }
445
446
447 /**
448 *
449 * \brief return the value of the sql, the sql will return only one value
450 * with the value
451 * \param $p_sql the sql stmt example :select s_value from
452 * document_state where s_id=2
453 * \param $p_array if array is not null we use the ExecSqlParm (safer)
454 * \see exec_sql
455 * \note print a warning if several value are found, if only the first value is needed
456 * consider using a LIMIT clause
457 * \return only the first value or an empty string if nothing is found
458 */
459
460 function get_value($p_sql, $p_array = null)
461 {
462 try {
463 $this->ret = $this->exec_sql($p_sql, $p_array);
464 $r = pg_num_rows($this->ret);
465 if ($r == 0)
466 return "";
467 if ($r > 1) {
468 $array = pg_fetch_all($this->ret);
469 throw new Exception("Attention $p_sql retourne " . pg_num_rows($this->ret) . " valeurs " .
470 var_export($p_array, true) . " values=" . var_export($array, true));
471 }
472 $r = pg_fetch_row($this->ret, 0);
473 return $r[0];
474
475 } catch (Exception $ex) {
476 throw($ex);
477 }
478 }
479
480 /**
481 * @brief return the number of rows affected by the previous query
482 */
483 function get_affected()
484 {
485 return Database::num_row($this->ret);
486 }
487
488 /**
489 * \brief purpose return the result of a sql statment
490 * in a array
491 * \param $p_sql sql query
492 * \param $p_array if not null we use ExecSqlParam
493 * \param $p_mode is PGSQL_ASSOC, PGSQL_BOTH or PGSQL_NUM (default PGSQL_ASSOC)
494 * \return false if nothing is found
495 */
496
497 function get_array($p_sql, $p_array = null,$p_mode=PGSQL_ASSOC)
498 {
499 $r = $this->exec_sql($p_sql, $p_array,$p_mode);
500
501 if (pg_num_rows($r) == 0)
502 return array();
503 $array = pg_fetch_all($r,$p_mode);
504 return $array;
505 }
506
507 /**
508 * @brief Returns only one row from a query
509 * @param string $p_sql
510 * @param array $p_array
511 * @return array , idx = column of the table or null if nothing is found
512 * @throws Exception if too many rows are found code 100
513 */
514 function get_row($p_sql, $p_array = NULL)
515 {
516 $array = $this->get_array($p_sql, $p_array);
517 if (empty($array)) return null;
518 if (count($array) == 1) return $array[0];
519 throw new Exception(_("Database:get_row retourne trop de lignes"), 100);
520 }
521
522 /**
523 * @brief Create a sequence
524 * @param string $p_name Sequence Name
525 * @param int $min starting value
526 */
527 function create_sequence($p_name, $min = 1)
528 {
529 if ($min < 1)
530 $min = 1;
531 $sql = "create sequence " . $p_name . " minvalue $min";
532 $this->exec_sql($sql);
533 }
534
535 /**
536 * \brief test if a sequence exist */
537 /* \return true if the seq. exist otherwise false
538 */
539
540 function exist_sequence($p_name)
541 {
542 $r = $this->count_sql("select relname from pg_class where relname=lower($1)", array($p_name));
543 if ($r == 0)
544 return false;
545 return true;
546 }
547
548 /**
549 * \brief test if a table exist
550 * \param $p_name table name
551 * \param $schema name of the schema default public
552 * \return true if a table exist otherwise false
553 */
554
555 function exist_table($p_name, $p_schema = 'public')
556 {
557 $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));
558 if ($r == 0)
559 return false;
560 return true;
561 }
562
563 /**
564 * Check if a column exists in a table
565 * @param $col : column name
566 * @param $table :table name
567 * @param $schema :schema name, default public
568 * @return true or false
569 */
570 function exist_column($col, $table, $schema)
571 {
572 $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));
573 if ($r > 0)
574 return true;
575 return false;
576 }
577
578
579 /**
580 * Count the database name in a system view
581 * @param $p_name string database name
582 * @return number of database found (normally 0 or 1)
583 */
584 function exist_database($p_name)
585 {
586 $database_exist = $this->get_value('select count(*)
587 from pg_catalog.pg_database where datname = lower($1)', array($p_name));
588 return $database_exist;
589 }
590
591 /**
592 * @brief check if the large object exists
593 * @param $p_oid of the large object
594 * @return return true if the large obj exist or false if not
595 */
596 function exist_blob($p_oid)
597 {
598 $r = $this->get_value('select count(*) from pg_largeobject_metadata where oid=$1'
599 , array($p_oid));
600 if ($r > 0)
601 return true;
602 else
603 return false;
604 }
605
606 /*
607 *!\brief test if a view exist
608 * \return true if the view. exist otherwise false
609 */
610
611 function exist_view($p_name)
612 {
613 $r = $this->count_sql("select viewname from pg_views where viewname=lower($1)", array($p_name));
614 if ($r == 0)
615 return false;
616 return true;
617 }
618
619 /***
620 * @brief test if a schema exists
621 * @return true if the schemas exists otherwise false
622 */
623
624 function exist_schema($p_name)
625 {
626 $r = $this->count_sql("select nspname from pg_namespace where nspname=lower($1)", array($p_name));
627 if ($r == 0)
628 return false;
629 return true;
630 }
631
632 /**
633 * \brief create a string containing the value separated by comma
634 * for use in a SQL in statement
635 * \return the string or empty if nothing is found
636 * \see fid_card.php
637 */
638
639 function make_list($sql, $p_array = null)
640 {
641 if ($p_array == null) {
642 $aArray = $this->get_array($sql);
643 } else {
644 $aArray = $this->get_array($sql, $p_array);
645 }
646 if (empty($aArray))
647 return "";
648 $aIdx = array_keys($aArray[0]);
649 $idx = $aIdx[0];
650 $ret = "";
651 $f = "";
652 for ($i = 0; $i < count($aArray); $i++) {
653 $row = $aArray[$i];
654 $ret .= $f . $aArray[$i][$idx];
655 $f = ',';
656 }
657 $ret = trim($ret, ',');
658 return $ret;
659 }
660
661 /**
662 * \brief make a array with the sql.
663 *
664 * \param $p_sql sql statement, only the first two column will be returned in
665 * an array. The first col. is the label and the second the value
666 * \param $p_null if the array start with a null value Yes = 1 , No=0
667 * \param $p_array is the array with the bind value
668 * \note this function is used with ISelect when it is needed to have a list of
669 * options.
670 * \return: a double array like
671 * \verbatim
672 * Array
673 * (
674 * [0] => Array
675 * (
676 * [value] => 1
677 * [label] => Marchandise A
678 * )
679 *
680 * [1] => Array
681 * (
682 * [value] => 2
683 * [label] => Marchandise B
684 * )
685 *
686 * [2] => Array
687 * (
688 * [value] => 3
689 * [label] => Marchandise C
690 * )
691 * )
692 * \endverbatim
693 * \see ISelect
694 */
695
696 function make_array($p_sql, $p_null = 0, $p_array = null)
697 {
698 $a = $this->exec_sql($p_sql, $p_array);
699 $max = pg_num_rows($a);
700 if ($max == 0 && $p_null == 0)
701 return null;
702 for ($i = 0; $i < $max; $i++) {
703 $row = pg_fetch_row($a);
704 $r[$i]['value'] = $row[0];
705 $r[$i]['label'] = h($row[1]);
706 }
707 // add a blank item ?
708 if ($p_null == 1) {
709 for ($i = $max; $i != 0; $i--) {
710 $r[$i]['value'] = $r[$i - 1]['value'];
711 $r[$i]['label'] = $r[$i - 1]['label'];
712 }
713 $r[0]['value'] = -1;
714 $r[0]['label'] = " ";
715 } // if ( $p_null == 1 )
716
717 return $r;
718 }
719
720 /***
721 * \brief Save one or several documents into the database , it just puts the file in the database
722 * and returns the corresponding OID , the mimetype , size ... of the document
723 * must be set in the calling function.
724 *
725 * \param name of the variable in $_FILES
726 * \param $only_oid (bool) (default :true) false : return filename and oid in an array , true only OID,
727 * \return $oid of the lob file if success
728 * false if a error occurs or if there is no file to upload
729 * array(oid, filename) if $only_oid is true
730 *
731 */
732
733 function upload($p_name,$only_oid = false)
734 {
735
736 //var $a : 0 we're in a transaction, 1 we are not in a transaction
737 $a=0;
738 if ( $this->status() !== PGSQL_TRANSACTION_INTRANS ) {
739 $a=1;
740 $this->start();
741 }
742
743 /* there is no file to upload */
744 if ($_FILES[$p_name]["error"] == UPLOAD_ERR_NO_FILE) {
745 \record_log("DC759: error upload file".var_export($_FILES, true));
746 if ( $a==1) { $this->rollback(); }
747 return false;
748 }
749
750 $new_name = tempnam($_ENV['TMP'], $p_name);
751 if ($_FILES[$p_name]["error"] > 0) {
752 \record_log("DC740: error upload file".var_export($_FILES, true));
753 if ( $a==1) { $this->rollback(); }
754 return false;
755 }
756 if (strlen($_FILES[$p_name]['tmp_name']) != 0) {
757 if (move_uploaded_file($_FILES[$p_name]['tmp_name'], $new_name)) {
758 // echo "Image saved";
759 $oid = pg_lo_import($this->db, $new_name);
760 if ($oid == false) {
761 \record_log("DC747: error upload file".var_export($_FILES, true). "SQL MESSAGE". pg_last_error($this->db));
762 $this->rollback();
763 return false;
764 }
765 if ( $a == 1 ) { $this->commit(); }
766 if ($only_oid ){
767 return $oid;
768 }else {
769 return ["oid"=>$oid,'filename'=>$new_name];
770 }
771 } else {
772 \record_log("DC754: move_uploaded fails".var_export($_FILES, true));
773 $this->rollback();
774 return false;
775 }
776 }
777
778 \record_log("DC576: Files error names empty".var_export($_FILES, true));
779 if ( $a == 1) { $this->commit(); }
780 return false;
781 }
782 /**
783 * @brief large_object writee: create a Large object if oid is not given
784 * with data content in a binaray
785 * @param $binary_data (raw data) binary
786 * @returns $oid of the LO, false if it fails
787 */
788 function lo_write($binary_data)
789 {
790 //var $a : 0 where in a transaction, 1 we are not in a transaction
791 $a=0;
792 if ( $this->status() !== PGSQL_TRANSACTION_INTRANS ) {
793 $a=1;
794 $this->start();
795 }
796
797 $oid= pg_lo_create($this->db);
798
799 if ( ($handle=pg_lo_open($this->db,$oid,"w")) == false ) { return false ;}
800 pg_lo_write($handle, $binary_data);
801 pg_lo_close($handle);
802 if ( $a==1) { $this->commit(); }
803 return $oid;
804
805 }
806 /**
807 * @brief read a Large object with data content in a binary
808 * @param $oid (int8) oid of the large object
809 * @returns $binary_data (raw data) binary
810 */
811 function lo_read($oid)
812 {
813 //var $a : 0 where in a transaction, 1 we are not in a transaction
814 $a=0;
815 if ( $this->status() !== PGSQL_TRANSACTION_INTRANS ) {
816 $a=1;
817 $this->start();
818 }
819
820 $handle=pg_lo_open($this->db,$oid,"r");
821 if ( $handle == false ) { return false ;}
822 // set position end of the LO
823 pg_lo_seek($handle, 0, PGSQL_SEEK_END);
824 // get the size
825 $size= pg_lo_tell($handle);
826 // set position to start
827 pg_lo_seek($handle, 0, PGSQL_SEEK_SET);
828 // read the comùplete LOB
829 $binary_data = pg_lo_read($handle,$size );
830 pg_lo_close($handle);
831 if ( $a==1) { $this->commit(); }
832 return $binary_data;
833 }
834 /**
835 * @brief replace a Large object with data content in a binary
836 * @param $oid (int8) oid of the large object
837 * @param $binary_data (raw data) binary
838 * @returns $oid of the LO, false if it fails
839 */
840 function lo_replace($binary_data, $oid) {
841 $a = 0;
842 if ($this->status() !== PGSQL_TRANSACTION_INTRANS) {
843 $a = 1;
844 $this->start();
845 }
846 $handle = pg_lo_open($this->db, $oid, "w");
847 if ( $handle == false ) { return false ;}
848 pg_lo_truncate($handle, 0);
849 pg_lo_write($handle, $binary_data);
850 pg_lo_close($handle);
851 if ($a == 1) {
852 $this->commit();
853 }
854 return $oid;
855 }
856
857 /**
858 * \brief wrapper for the function pg_num_rows
859 * \param $ret is the result of a exec_sql
860 * \return number of line affected
861 */
862
863 static function num_row($ret)
864 {
865 return pg_num_rows($ret);
866 }
867
868 /**
869 * \brief wrapper for the function pg_fetch_array
870 * \param $ret is the result of a pg_exec
871 * \param $p_indice is the index
872 * \param $p_mode is PGSQL_ASSOC, PGSQL_BOTH or PGSQL_NUM (default PGSQL_ASSOC)
873 * \return $array of column
874 */
875
876 static function fetch_array($ret, $p_indice = 0,$p_mode=PGSQL_ASSOC)
877 {
878 return pg_fetch_array($ret, $p_indice,$p_mode);
879 }
880
881 /**
882 * \brief wrapper for the function pg_fetch_all
883 * \param $ret is the result of pg_exec (exec_sql)
884 * \param $p_mode is PGSQL_ASSOC, PGSQL_BOTH or PGSQL_NUM (default PGSQL_ASSOC)
885 * \return double array (row x col ) or false
886 */
887
888 static function fetch_all($ret,$p_mode= PGSQL_ASSOC)
889 {
890 return pg_fetch_all($ret,$p_mode);
891 }
892
893 /**
894 * \brief wrapper for the function pg_fetch_all
895 * \param $ret is the result of pg_exec (exec_sql)
896 * \param $p_row is the indice of the row
897 * \param $p_col is the indice of the col
898 * \return a string or an integer
899 */
900
901 static function fetch_result($ret, $p_row = 0, $p_col = 0)
902 {
903 return pg_fetch_result($ret, $p_row, $p_col);
904 }
905
906 /**
907 * \brief wrapper for the function pg_fetch_row
908 * \param $ret is the result of pg_exec (exec_sql)
909 * \param $p_row is the indice of the row
910 * \return an array indexed from 0
911 */
912 static function fetch_row($ret, $p_row)
913 {
914 return pg_fetch_row($ret, $p_row);
915 }
916
917 /**
918 * \brief wrapper for the function pg_lo_unlink
919 * \param $p_oid is the of oid
920 * \return return the result of the operation : false == fails
921 */
922
923 function lo_unlink($p_oid)
924 {
925 if (!$this->exist_blob($p_oid)) return;
926 return pg_lo_unlink($this->db, $p_oid);
927 }
928
929 /**\brief wrapper for the function pg_prepare
930 * \param $p_string string name for pg_prepare function
931 * \param $p_sql is the sql to prepare
932 * \return return the result of the operation
933 */
934
935 function prepare($p_string, $p_sql)
936 {
937 return pg_prepare($this->db, $p_string, $p_sql);
938 }
939
940 /**
941 * \brief wrapper for the function pg_execute
942 * \param $p_string string name of the stmt given in pg_prepare function
943 * \param $p_array contains the variables
944 * \note set this->ret to the return of pg_execute
945 * \return return the result of the operation,
946 */
947
948 function execute($p_string, $p_array)
949 {
950 $this->ret = pg_execute($this->db, $p_string, $p_array);
951 return $this->ret;
952 }
953
954 /**
955 * \brief wrapper for the function pg_lo_export
956 * \param $p_oid is the oid of the log
957 * \param $tmp_file is the file
958 * \return result of the operation
959 */
960
961 function lo_export($p_oid, $tmp_file)
962 {
963 return pg_lo_export($this->db, $p_oid, $tmp_file);
964 }
965
966 /**
967 * \brief wrapper for the function pg_lo_export
968 * \param $p_filename is the filename
969 * \param $tmp is the file
970 * \return result of the operation
971 */
972
973 function lo_import($p_filename)
974 {
975 return pg_lo_import($this->db, $p_filename);
976 }
977
978 /**
979 * \brief wrapper for the function pg_escape_string
980 * \param $p_string is the string to escape
981 * \return escaped string
982 */
983
984 static function escape_string($p_string)
985 {
986 static $cn=null;
987 if ( $cn==null) $cn=new Database();
988 return pg_escape_string($cn->db,$p_string);
989 }
990
991 /**
992 * \brief wrapper for the function pg_close
993 */
994
995 function close()
996 {
997 if ($this->is_open) pg_close($this->db);
998 $this->is_open = FALSE;
999 }
1000
1001 /**
1002 * \brief
1003 * \param
1004 * \return
1005 * \note
1006 * \see
1007 */
1008
1009 function __toString()
1010 {
1011 return "database ";
1012 }
1013
1014 static function test_me()
1015 {
1016
1017 }
1018 /**
1019 * @brief get the transaction status :
1020 * The status can be
1021 * - PGSQL_TRANSACTION_IDLE (currently idle),
1022 * - PGSQL_TRANSACTION_ACTIVE (a command is in progress),
1023 * - PGSQL_TRANSACTION_INTRANS (idle, in a valid transaction block),
1024 * - PGSQL_TRANSACTION_INERROR (idle, in a failed transaction block).
1025 * - PGSQL_TRANSACTION_UNKNOWN is reported if the connection is bad.
1026 * - PGSQL_TRANSACTION_ACTIVE is reported only when a query has been sent to the server
1027 * and not yet completed.
1028 * * @return PGSQL_TRANSACTION_IDLE | PGSQL_TRANSACTION_ACTIVE | PGSQL_TRANSACTION_INTRANS | PGSQL_TRANSACTION_INERROR | PGSQL_TRANSACTION_UNKNOWN | PGSQL_TRANSACTION_ACTIVE
1029 */
1030 function status()
1031 {
1032 return pg_transaction_status($this->db);
1033 }
1034
1035
1036 /**
1037 * @brief Find all lob and remove those which are not used by any tables
1038 *
1039 */
1041 {
1042 // find all columns of type lob
1043 $sql = "
1044 select table_schema,table_name,column_name
1045 from
1046 information_schema.columns
1047 where table_schema not in ('information_schema','pg_catalog')
1048 and data_type='oid'";
1049 $all_lob = "
1050 select oid,'N' as used from pg_largeobject_metadata
1051 ";
1052 $a_table = $this->get_array($sql);
1053 $a_lob = $this->get_array($all_lob);
1054 if ($a_table == false || $a_lob == false) return;
1055 // for each lob
1056 $nb_lob = count($a_lob);
1057 $nb_table = count($a_table);
1058 for ($i = 0; $i < $nb_lob; $i++) {
1059 $lob = $a_lob[$i]['oid'];
1060 if ($a_lob[$i]['used'] == 'Y') continue;
1061 for ($j = 0; $j < $nb_table; $j++) {
1062 if ($a_lob[$i]['used'] == 'Y') continue;
1063 $check = $this->get_value(" select count(*) from " .
1064 $a_table[$j]['table_schema'] . "." . $a_table[$j]['table_name'] .
1065 " where " .
1066 $a_table[$j]['column_name'] . "=$1", array($lob));
1067 if ($check != 0)
1068 $a_lob[$i]['used'] = 'Y';
1069
1070 }
1071 }
1072 for ($i = 0; $i < $nb_lob; $i++) {
1073 if ($a_lob[$i]['used'] == 'Y') continue;
1074 $this->lo_unlink($a_lob[$i]['oid']);
1075 }
1076 }
1077
1078 /**
1079 * @brief Check if a prepared statement already exists or not
1080 * @param string $query_name name of the prepared query
1081 * @return boolean false is not yet prepared
1082 */
1083 function is_prepare($query_name)
1084 {
1085 $nb_prepared = $this->get_value("select count(*) from pg_prepared_statements where name=$1", [$query_name]);
1086 if ($nb_prepared == 0) return FALSE;
1087 return TRUE;
1088 }
1089
1090 /**
1091 * @brief with the handle of a successull query, echo each row into CSV and
1092 * send it directly to output. To save it into a file, it is needed to send first the HEADER as CSV. If there are
1093 *less column than column defined in $aheader, then the columns not included in the header are not displaid
1094 *
1095 * @param handle $ret handle to a query
1096 * @param array $aheader double array, each item of the array contains (idx : title, type)
1097 * a key type (num) and a key title
1098 */
1099 function query_to_csv($ret, $aheader)
1100 {
1101 $csv = new Noalyss_Csv("db-query");
1102 $a_header = [];
1103 for ($i = 0; $i < count($aheader); $i++) {
1104 $a_header[] = $aheader[$i]['title'];
1105 }
1106 $csv->write_header($a_header);
1107
1108 // fetch all the rows
1110 for ($i = 0; $i < $nb; $i++) {
1112 // for each rows, for each value
1113 $e=0;
1114 foreach ($row as $row_item){
1115 if ( $e >= count($a_header)) break;
1116 switch ($aheader[$e]['type']) {
1117 case 'num':
1118 $csv->add($row_item, "number");
1119 break;
1120 default:
1121 $csv->add($row_item);
1122 }
1123 $e++;
1124 }
1125 $csv->write();
1126 }
1127 }
1128 /**
1129 * @brief Returns the number of columns in a ret
1130 * @param handler $p_ret handler to a query
1131 */
1132 static function nb_column($p_ret) {
1133 return pg_num_fields($p_ret);
1134 }
1135 /**
1136 * @brief FInd if a SQL Select has a SQL stmt to inject or damage Data
1137 * When a SELECT SQL string is build, this string could contain a SQL attempt to damage data,
1138 *so the statement DELETE TRUNCATE ... are forbidden. Throw an exception EXC_INVALID
1139 *
1140 */
1141 function search_sql_inject($p_sql)
1142 {
1143 $forbid_sql=array("update","delete","truncate","insert");
1144 // protect against SQL inject
1145 foreach ($forbid_sql as $forbid_key) {
1146 if (stripos($p_sql,$forbid_key) !== false)
1147 {
1148 throw new Exception(_("Possible SQL inject"),EXC_INVALID);
1149 }
1150
1151 }
1152 }
1153
1154 /**
1155 * @brief clear a prepare stmt
1156 * @see DatabaseCore::is_prepare
1157 * @see DatabaseCore::execute
1158 * @see DatabaseCore::prepare
1159 * @param $sql_name name of the prepare SQL
1160 */
1161 function clear_prepare($sql_name)
1162 {
1163 pg_exec($this->db,sprintf('DEALLOCATE "%s"'),DatabaseCore::escape_string($sql_name));
1164 }
1165 /**
1166 * @brief clear all prepare stmt
1167 * @see DatabaseCore::is_prepare
1168 * @see DatabaseCore::execute
1169 * @see DatabaseCore::prepare
1170 */
1172 {
1173 pg_exec($this->db,'DEALLOCATE ALL');
1174 }
1175}
1176
1177/* test::test_me(); */
record_log($p_message)
Record an error message into the log file of the server or in the log folder of NOALYSS Record also t...
catch(Exception $exc) if(! $g_user->can_write_action($ag_id)) $r
h( $row[ 'oa_description'])
$name size
_("actif, passif,charge,...")
$ex
This class allow you to connect to the postgresql database, execute sql, retrieve data.
lo_read($oid)
read a Large object with data content in a binary
commit()
Commit the transaction.
start()
: start a transaction
close()
wrapper for the function pg_close
set_encoding($p_charset)
make_list($sql, $p_array=null)
create a string containing the value separated by comma for use in a SQL in statement
alter_seq($p_name, $min)
alter the sequence value
$db
database connection
static escape_string($p_string)
wrapper for the function pg_escape_string
exist_column($col, $table, $schema)
Check if a column exists in a table.
lo_export($p_oid, $tmp_file)
wrapper for the function pg_lo_export
$dbhost
!< $dbport (int) Database port
static fetch_result($ret, $p_row=0, $p_col=0)
wrapper for the function pg_fetch_all
$sql
last SQL stmt executed
execute($p_string, $p_array)
wrapper for the function pg_execute
rollback()
rollback the current transaction
is_prepare($query_name)
Check if a prepared statement already exists or not.
get_value($p_sql, $p_array=null)
return the value of the sql, the sql will return only one value with the value
size($p_ret=null)
return the number of rows found by the last query, or the number of rows from $p_ret
get_sql()
last SQL stmt executed
count($p_ret=null)
synomym for size()
exist_sequence($p_name)
test if a sequence exist
get_next_seq($p_seq)
get the next sequence value
fetch($p_indice, $p_mode=PGSQL_ASSOC)
fetch the $p_indice array from the last query
clear_all_prepare()
clear all prepare stmt
make_array($p_sql, $p_null=0, $p_array=null)
make a array with the sql.
exist_blob($p_oid)
check if the large object exists
static fetch_row($ret, $p_row)
wrapper for the function pg_fetch_row
clear_prepare($sql_name)
clear a prepare stmt
lo_import($p_filename)
wrapper for the function pg_lo_export
search_sql_inject($p_sql)
FInd if a SQL Select has a SQL stmt to inject or damage Data When a SELECT SQL string is build,...
upload($p_name, $only_oid=false)
Save one or several documents into the database , it just puts the file in the database and returns t...
static fetch_array($ret, $p_indice=0, $p_mode=PGSQL_ASSOC)
wrapper for the function pg_fetch_array
status()
get the transaction status : The status can be
get_affected()
return the number of rows affected by the previous query
$dbuser
!< $dbhost(string) Database host
get_current_seq($p_seq)
get the current sequence value
create_sequence($p_name, $min=1)
Create a sequence.
exec_sql($p_string, $p_array=null)
send a sql string to the database
lo_unlink($p_oid)
wrapper for the function pg_lo_unlink
set_sql($sql)
last SQL stmt executed
clean_orphan_lob()
Find all lob and remove those which are not used by any tables.
__construct($p_user, $p_password, $p_dbname, $p_host, $p_port)
!< $dbuser(string) Database user
lo_write($binary_data)
large_object writee: create a Large object if oid is not given with data content in a binaray
static fetch_all($ret, $p_mode=PGSQL_ASSOC)
wrapper for the function pg_fetch_all
get_array($p_sql, $p_array=null, $p_mode=PGSQL_ASSOC)
purpose return the result of a sql statment in a array
static num_row($ret)
wrapper for the function pg_num_rows
get_name()
return the name of the current database
execute_script($script)
Execute a sql script.
exist_database($p_name)
Count the database name in a system view.
query_to_csv($ret, $aheader)
with the handle of a successull query, echo each row into CSV and send it directly to output.
exist_schema($p_name)
test if a schema exists
$dbport
!< $dbname (string) Database name
count_sql($p_sql, $p_array=null)
Count the number of row returned by a sql statement.
lo_replace($binary_data, $oid)
replace a Large object with data content in a binary
exist_table($p_name, $p_schema='public')
test if a table exist
prepare($p_string, $p_sql)
wrapper for the function pg_prepare
static nb_column($p_ret)
Returns the number of columns in a ret.
get_row($p_sql, $p_array=NULL)
Returns only one row from a query.
contains the class for connecting to Noalyss
Manage the CSV : manage files and write CSV record.
const EXC_INVALID
Definition constant.php:358
if(in_array( $type, array( 'CHA', 'ACT', 'PASINV', 'PROINV')) &&$tot_deb< $tot_cred) if(in_array($type, array('PRO', 'PAS', 'ACTINV', 'CHAINV')) && $tot_deb > $tot_cred) $size
$new_name
$SecUser db
print
Type of printing.
$check
$table
Definition menu.inc.php:104
$script
Definition popup.php:131