Platform  3.1
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.DbObj.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @license http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ Anakeen - licence CC
5  * @package FDL
6 */
7 /**
8  * This class is a generic DB Class that can be used to create objects
9  * based on the description of a DB Table.
10  *
11  * @author Anakeen 2000
12  * @version $Id: Class.DbObj.php,v 1.58 2008/12/29 17:05:38 eric Exp $
13  * @license http://creativecommons.org/licenses/by-nc-sa/2.0/fr/ Anakeen - licence CC
14  * @package FDL
15  * @subpackage CORE
16  */
17 /**
18  */
19 
20 include_once ('Class.Log.php');
21 include_once ('Lib.Common.php');
22 
23 $CLASS_DBOBJ_PHP = '$Id: Class.DbObj.php,v 1.58 2008/12/29 17:05:38 eric Exp $';
24 /**
25  * This class is a generic DB Class that can be used to create objects
26  * based on the description of a DB Table. More Complex Objects will
27  * inherit from this basic Class.
28  *
29  */
30 class DbObj
31 {
32  /**
33  * the database connection resource
34  * @var resource
35  */
36  var $dbid = - 1;
37  /**
38  * coordinates to access to database
39  * @var string
40  */
41  var $dbaccess = '';
42  /**
43  * array of SQL fields use for the object
44  * @var array
45  */
46  var $fields = array(
47  '*'
48  );
49  /**
50  * name of the SQL table
51  * @var string
52  */
53  var $dbtable = '';
54 
55  var $criterias = array();
56  /**
57  * array of other SQL fields, not in attribute of object
58  * @var array
59  */
60  var $sup_fields = array();
61  var $sup_where = array();
62  var $sup_tables = array();
63  var $fulltextfields = array();
64  /**
65  * sql field to order
66  * @var string
67  */
68  var $order_by = "";
69  /**
70  * indicates if fields has been affected
71  * @var string
72  * @see Affect()
73  */
74  var $isset = false; // indicate if fields has been affected (call affect methods)
75  static $savepoint = array();
76  /**
77  * @var string error message
78  */
79  public $msg_err = '';
80  /**
81  * @var int
82  */
83  public $err_code = '';
84  /**
85  * @var ressource
86  */
87  public $res = null;
88  /**
89  * @var bool
90  */
91  public $debug = false;
92  //----------------------------------------------------------------------------
93 
94  /**
95  * Database Object constructor
96  *
97  *
98  * @param string $dbaccess database specification
99  * @param int $id identificator of the object
100  * @param array $res array of result issue to QueryDb {@link QueryDb::Query()}
101  * @param resource $dbid the database connection resource
102  * @return bool false if error occured
103  */
104  function __construct($dbaccess = '', $id = '', $res = '', $dbid = 0)
105  {
106  if (!$dbaccess) $dbaccess = getDbAccess();
107  $this->dbaccess = $dbaccess;
108  $this->init_dbid();
109  //global ${$this->oname};
110  $this->log = new Log("", "DbObj", $this->dbtable);
111 
112  if ($this->dbid == 0) {
113  $this->dbid = - 1;
114  }
115 
116  $this->selectstring = "";
117  // SELECTED FIELDS
118  reset($this->fields);
119  foreach ($this->fields as $k => $v) {
120  $this->selectstring = $this->selectstring . $this->dbtable . "." . $v . ",";
121  $this->$v = "";
122  }
123 
124  reset($this->sup_fields);
125  foreach ($this->sup_fields as $k => $v) {
126  $this->selectstring = $this->selectstring . "" . $v . ",";
127  $this->$v = "";
128  }
129  $this->selectstring = substr($this->selectstring, 0, strlen($this->selectstring) - 1);
130  // select with the id
131  if (($id != '') || (is_array($id)) || (!isset($this->id_fields[0]))) {
132  $ret = $this->Select($id);
133 
134  return ($ret);
135  }
136  // affect with a query result
137  if (is_array($res)) {
138  $this->Affect($res);
139  }
140 
141  return TRUE;
142  }
143 
144  function Select($id)
145  {
146  if ($this->dbid == - 1) return FALSE;
147 
148  $msg = $this->PreSelect($id);
149  if ($msg != '') return $msg;
150 
151  if ($this->dbtable == '') {
152  return ("error : No Tables");
153  }
154  $fromstr = "{$this->dbtable}";
155  if (is_array($this->sup_tables)) {
156  reset($this->sup_tables);
157  foreach ($this->sup_tables as $k => $v) {
158  $fromstr.= "," . $v;
159  }
160  }
161  $sql = "select {$this->selectstring} from {$fromstr} ";
162 
163  $count = 0;
164  if (is_array($id)) {
165  $count = 0;
166  $wherestr = " where ";
167  reset($this->id_fields);
168  foreach ($this->id_fields as $k => $v) {
169  if ($count > 0) {
170  $wherestr = $wherestr . " AND ";
171  }
172  $wherestr = $wherestr . "( " . $this->dbtable . "." . $v . "=E'" . pg_escape_string($id[$k]) . "' )";
173  $count = $count + 1;
174  //$this->$v = $id[$k];
175 
176  }
177  } else {
178  if (isset($this->id_fields[0])) {
179  $k = $this->id_fields[0];
180  //$this->$k = $id;
181  $wherestr = "where " . $this->dbtable . "." . $this->id_fields[0] . "=E'" . pg_escape_string($id) . "'";
182  } else {
183  $wherestr = "";
184  }
185  }
186  if (is_array($this->sup_where)) {
187  reset($this->sup_where);
188  foreach ($this->sup_where as $k => $v) {
189  $wherestr = $wherestr . " AND ";
190  $wherestr = $wherestr . "( " . $v . " )";
191  $count = $count + 1;
192  }
193  }
194 
195  $sql = $sql . " " . $wherestr;
196 
197  $resultat = $this->exec_query($sql);
198 
199  if ($this->numrows() > 0) {
200  $res = $this->fetch_array(0);
201  $retour = $this->Affect($res);
202  } else {
203  return FALSE;
204  }
205  $msg = $this->PostSelect($id);
206  if ($msg != '') return $msg;
207  return TRUE;
208  }
209  /**
210  * get all values in array
211  * @return array
212  */
213  function getValues()
214  {
215  $r = array();
216  foreach ($this->fields as $k => $v) {
217  $r[$v] = $this->$v;
218  }
219  return $r;
220  }
221  /**
222  * affect object specific column values from this item
223  * use only when object is already affected
224  * @param array $fields sql field to affect
225  * @return bool true if OK false else
226  */
228  {
229  if ($this->dbid == - 1) return FALSE;
230 
231  if (!$this->isAffected()) return false;
232  if (count($fields) == 0) return true;
233  if ($this->dbtable == '') {
234  return ("error : No Tables");
235  }
236  $fromstr = $this->dbtable;
237 
238  foreach ($this->id_fields as $id) {
239  $w[] = "($id = E'" . pg_escape_string($this->$id) . "') ";
240  }
241  $sqlwhere = implode("and", $w);
242  $sqlselect = implode(",", $fields);
243 
244  $sql = "select $sqlselect from $fromstr where $sqlwhere";
245 
246  $resultat = $this->exec_query($sql);
247 
248  if ($this->numrows() > 0) {
249  $res = $this->fetch_array(0);
250  $retour = $this->Affect($res);
251  } else {
252  return FALSE;
253  }
254  return TRUE;
255  }
256 
257  function Affect($array)
258  {
259  reset($array);
260  foreach ($array as $k => $v) {
261  if (!is_integer($k)) {
262  $this->$k = $v;
263  }
264  }
265  $this->Complete();
266  $this->isset = true;
267  }
268  /**
269  * verify that the object exists
270  *
271  * if true values of the object has been set
272  * @return bool
273  */
274  function isAffected()
275  {
276  return $this->isset;
277  }
278 
279  function Complete()
280  {
281  // This function should be replaced by the Child Class
282 
283  }
284  /**
285  * Method use before Add method
286  * This method should be replaced by the Child Class
287  *
288  * @return string error message, if no error empty string
289  * @see Add()
290  */
291  function PreInsert()
292  {
293  // This function should be replaced by the Child Class
294 
295  }
296  /**
297  * Method use after Add method
298  * This method should be replaced by the Child Class
299  *
300  * @return string error message, if no error empty string, if message
301  * error not empty the Add method is not completed
302  * @see Add()
303  */
304  function PostInsert()
305  {
306  // This function should be replaced by the Child Class
307 
308  }
309  /**
310  * Method use before Modify method
311  * This method should be replaced by the Child Class
312  *
313  * @return string error message, if no error empty string
314  * @see Modify()
315  */
316  function PreUpdate()
317  {
318  // This function should be replaced by the Child Class
319 
320  }
321  /**
322  * Method use after Modify method
323  * This method should be replaced by the Child Class
324  *
325  * @return string error message, if no error empty string, if message
326  * error not empty the Modify method is not completed
327  * @see Modify()
328  */
329  function PostUpdate()
330  {
331  // This function should be replaced by the Child Class
332 
333  }
334  function PreDelete()
335  {
336  // This function should be replaced by the Child Class
337 
338  }
339  function PostDelete()
340  {
341  // This function should be replaced by the Child Class
342 
343  }
344  function PreSelect($id)
345  {
346  // This function should be replaced by the Child Class
347 
348  }
349  function PostSelect($id)
350  {
351  // This function should be replaced by the Child Class
352 
353  }
354  /**
355  * Add the object to the database
356  * @param bool $nopost PostInsert method not apply if true
357  * @param bool $nopost PreInsert method not apply if true
358  * @return string error message, if no error empty string
359  * @see PreInsert()
360  * @see PostInsert()
361  */
362  function Add($nopost = false, $nopre = false)
363  {
364  if ($this->dbid == - 1) return FALSE;
365 
366  if (!$nopre) $msg = $this->PreInsert();
367  if ($msg != '') return $msg;
368 
369  $sfields = implode(",", $this->fields);
370  $sql = "insert into " . $this->dbtable . "($sfields) values (";
371 
372  $valstring = "";
373  reset($this->fields);
374  foreach ($this->fields as $k => $v) {
375  $valstring = $valstring . $this->lw($this->$v) . ",";
376  }
377  $valstring = substr($valstring, 0, strlen($valstring) - 1);
378  $sql = $sql . $valstring . ")";
379  // requery execution
380  $msg_err = $this->exec_query($sql);
381 
382  if ($msg_err != '') {
383  return $msg_err;
384  }
385  $this->isset = true;
386  if (!$nopost) $msg = $this->PostInsert();
387  if ($msg != '') return $msg;
388  }
389  /**
390  * Add the object to the database
391  * @param bool $nopost PostUpdate() and method not apply if true
392  * @param string $sfields only this column will ne updated if empty all fields
393  * @param bool $nopre PreUpdate() method not apply if true
394  * @return string error message, if no error empty string
395  * @see PreUpdate()
396  * @see PostUpdate()
397  */
398  function Modify($nopost = false, $sfields = "", $nopre = false)
399  {
400  $msg = '';
401  if ($this->dbid == - 1) return FALSE;
402  if (!$nopre) $msg = $this->PreUpdate();
403  if ($msg != '') return $msg;
404  $sql = "update " . $this->dbtable . " set ";
405 
406  $nb_keys = 0;
407 
408  if (!is_array($sfields)) $fields = $this->fields;
409  else {
410  $fields = $sfields;
411  foreach ($this->id_fields as $k => $v) $fields[] = $v;
412  }
413 
414  $wstr = "";
415  foreach ($this->id_fields as $k => $v) {
416  $notset[$v] = "Y";
417  $nb_keys++;
418  $val = pg_escape_string($this->$v);
419  $wstr = $wstr . " " . $v . "=E'" . $val . "' AND";
420  }
421 
422  $setstr = "";
423  foreach ($fields as $k => $v) {
424  if (!isset($notset[$v])) {
425  $setstr = $setstr . " " . $v . "=" . $this->lw($this->$v) . ",";
426  }
427  }
428  $setstr = substr($setstr, 0, strlen($setstr) - 1);
429  $wstr = substr($wstr, 0, strlen($wstr) - 3);
430  $sql.= $setstr;
431  if ($nb_keys > 0) {
432  $sql.= " where " . $wstr . ";";
433  }
434 
435  $msg_err = $this->exec_query($sql);
436  // sortie
437  if ($msg_err != '') {
438  return $msg_err;
439  }
440 
441  if (!$nopost) $msg = $this->PostUpdate();
442 
443  if ($msg != '') return $msg;
444  }
445 
446  function Delete($nopost = false)
447  {
448  $msg = $this->PreDelete();
449  if ($msg != '') return $msg;
450  $wherestr = "";
451  $count = 0;
452 
453  reset($this->id_fields);
454  foreach ($this->id_fields as $k => $v) {
455  if ($count > 0) {
456  $wherestr = $wherestr . " AND ";
457  }
458  $wherestr = $wherestr . "( " . $v . "=E'" . pg_escape_string($this->$v) . "' )";
459  $count++;
460  }
461  // suppression de l'enregistrement
462  $sql = "delete from " . $this->dbtable . " where " . $wherestr . ";";
463 
464  $msg_err = $this->exec_query($sql);
465 
466  if ($msg_err != '') {
467  return $msg_err;
468  }
469 
470  if (!$nopost) $msg = $this->PostDelete();
471  if ($msg != '') return $msg;
472  }
473  /**
474  * Add several objects to the database
475  * no post neither preInsert are called
476  * @param bool $nopost PostInsert method not apply if true
477  * @return string error message, if no error empty string
478  * @see PreInsert()
479  * @see PostInsert()
480  */
481  function Adds(&$tcopy, $nopost = false)
482  {
483  if ($this->dbid == - 1) return FALSE;
484  if (!is_array($tcopy)) return FALSE;
485 
486  $sfields = implode(",", $this->fields);
487  $sql = "copy " . $this->dbtable . "($sfields) from STDIN;\n";
488 
489  $trow = array();
490  foreach ($tcopy as $kc => $vc) {
491  $trow[$kc] = "";
492  foreach ($this->fields as $k => $v) {
493  $trow[$kc].= "" . ((isset($vc[$v])) ? $vc[$v] : ((($this->$v) != '') ? $this->$v : '\N')) . "\t";
494  //$trow[$kc][$k] .= ((isset($vc[$v]))?$vc[$v]:$this->$v);
495 
496  }
497  $trow[$kc] = substr($trow[$kc], 0, -1);
498  }
499  // query execution
500  $berr = pg_copy_from($this->dbid, $this->dbtable, $trow, "\t");
501 
502  if (!$berr) return sprintf(_("DbObj::Adds error in multiple insertion"));
503 
504  if (!$nopost) $msg = $this->PostInsert();
505  if ($msg != '') return $msg;
506  }
507  function lw($prop)
508  {
509  $result = (($prop == '') && ($prop !== 0)) ? "null" : "E'" . pg_escape_string($prop) . "'";
510  return $result;
511  }
512  function CloseConnect()
513  {
514  pg_close("$this->dbid");
515  return TRUE;
516  }
517 
518  function Create($nopost = false)
519  {
520  $msg = "";
521  if (isset($this->sqlcreate)) {
522  // step by step
523  if (is_array($this->sqlcreate)) {
524  foreach ($this->sqlcreate as $k => $sqlquery) {
525  $msg.= $this->exec_query($sqlquery, 1);
526  }
527  } else {
528  $sqlcmds = explode(";", $this->sqlcreate);
529  foreach ($sqlcmds as $k => $sqlquery) {
530  $msg.= $this->exec_query($sqlquery, 1);
531  }
532  }
533  $this->log->debug("DbObj::Create : {$this->sqlcreate}");
534  }
535  if (isset($this->sqlinit)) {
536  $msg = $this->exec_query($this->sqlinit, 1);
537  $this->log->debug("Init : {$this->sqlinit}");
538  }
539  if ($msg != '') {
540  $this->log->info("DbObj::Create $msg");
541  return $msg;
542  }
543  if (!$nopost) $this->PostInit();
544  return ($msg);
545  }
546 
547  function PostInit()
548  {
549  }
550 
551  function init_dbid()
552  {
553 
554  if ($this->dbaccess == "") {
555  // don't test if file exist or must be searched in include_path
556  $this->dbaccess = getDbAccess();
557  }
558  $this->dbid = getDbid($this->dbaccess);
559  return $this->dbid;
560  }
561  /**
562  * @param string $sql the query
563  * @param int $lvl level set to 0
564  * @param bool $prepare set to true to use pg_prepare, restrict to use single query
565  * @return string error message
566  */
567  function exec_query($sql, $lvl = 0, $prepare = false)
568  {
569  global $SQLDELAY, $SQLDEBUG;
570 
571  if ($sql == "") return '';
572 
573  if ($SQLDEBUG) $sqlt1 = microtime(); // to test delay of request
574  $this->init_dbid();
575  $this->log->debug("exec_query : $sql");
576 
577  $this->res = null;
578  $this->msg_err = '';
579  $this->err_code = '';
580 
581  if ($prepare) {
582  if (pg_send_prepare($this->dbid, '', $sql) === false) {
583  $this->msg_err = "Error preparing statement : " . pg_last_error($this->dbid);
584  error_log(__METHOD__ . " " . $this->msg_err);
585  return $this->msg_err;
586  }
587  $this->res = pg_get_result($this->dbid);
588  $this->msg_err = pg_result_error($this->res);
589  $this->err_code = pg_result_error_field($this->res, PGSQL_DIAG_SQLSTATE);
590 
591  if ($this->msg_err == "") {
592  if (pg_send_execute($this->dbid, '', array()) === false) {
593  $this->msg_err = "Error executing statement : " . pg_last_error($this->dbid);
594  error_log(__METHOD__ . " " . $this->msg_err);
595  return $this->msg_err;
596  }
597  $this->res = pg_get_result($this->dbid);
598  $this->msg_err = pg_result_error($this->res);
599  $this->err_code = pg_result_error_field($this->res, PGSQL_DIAG_SQLSTATE);
600  }
601  } else {
602  if (pg_send_query($this->dbid, $sql) === false) {
603  $this->msg_err = "Error sending query : " . pg_last_error($this->dbid);
604  error_log(__METHOD__ . " " . $this->msg_err);
605  return $this->msg_err;
606  }
607  $this->res = pg_get_result($this->dbid);
608  $this->msg_err = pg_result_error($this->res);
609  $this->err_code = pg_result_error_field($this->res, PGSQL_DIAG_SQLSTATE);
610  }
611 
612  if ($this->msg_err) error_log($this->msg_err);
613  $action_needed = "";
614  if ($lvl == 0) {
615  if ($this->err_code != "") {
616  // http://www.postgresql.org/docs/8.3/interactive/errcodes-appendix.html
617  switch ($this->err_code) {
618  case "42P01":
619  // UNDEFINED TABLE
620  $action_needed = "create";
621  break;
622 
623  case "42703":
624  // UNDEFINED COLUMN
625  $action_needed = "update";
626  break;
627 
628  case "42P07":
629  // DUPLICATE TABLE
630  $action_needed = "none";
631  break;
632 
633  default:
634  break;
635  }
636 
637  error_log(__METHOD__ . " [" . $this->msg_err . " (" . $this->err_code . ")]:$action_needed.[$sql]");
638  //print_r2(getDebugStack());print $sql;
639  //trigger_error('<pre>'.$this->msg_err."\n".$sql.'</pre>');
640 
641  }
642  }
643 
644  switch ($action_needed) {
645  case "create":
646  $st = $this->Create();
647  if ($st == "") {
648  $this->msg_err = $this->exec_query($sql);
649  } else {
650  return "Table {$this->dbtable} doesn't exist and can't be created";
651  }
652  break;
653 
654  case "update":
655  $this->log->warning("sql fail: $sql");
656  $this->log->warning("try update :: " . $this->msg_err);
657  $st = $this->Update();
658  if ($st == "") {
659  $this->msg_err = $this->exec_query($sql);
660  } else {
661  return "Table {$this->dbtable} cannot be updated";
662  }
663  break;
664 
665  case "none":
666  $this->msg_err = "";
667  break;
668 
669  default:
670  break;
671  }
672  if ($this->msg_err != "") {
673  $this->log->warning("exec_query :" . $sql);
674  $this->log->warning("PostgreSQL Error : " . $this->msg_err);
675  }
676 
677  if ($SQLDEBUG) {
678  global $TSQLDELAY;
679  $SQLDELAY+= microtime_diff(microtime() , $sqlt1); // to test delay of request
680  $TSQLDELAY[] = array(
681  "t" => sprintf("%.04f", microtime_diff(microtime() , $sqlt1)) ,
682  "s" => str_replace(array(
683  "from",
684  'where'
685  ) , array(
686  "\nfrom",
687  "\nwhere"
688  ) , $sql) ,
689  "st" => getDebugStack(1)
690  );
691  }
692 
693  return ($this->msg_err);
694  }
695 
696  function numrows()
697  {
698  if ($this->msg_err == "") {
699  return (pg_num_rows($this->res));
700  } else {
701  return (0);
702  }
703  }
704 
705  function fetch_array($c, $type = PGSQL_ASSOC)
706  {
707 
708  return (pg_fetch_array($this->res, $c, $type));
709  }
710 
711  function Update()
712  {
713  print $this->msg_err;
714  print (" - need update table " . $this->dbtable);
715  $this->log->error("need Update table " . $this->dbtable);
716  exit;
717  $this->log->info("Update table " . $this->dbtable);
718  // need to exec altering queries
719  $objupdate = new DbObj($this->dbaccess);
720  // ------------------------------
721  // first : save table to updated
722  $dumpfile = uniqid(getTmpDir() . "/" . $this->dbtable);
723  $err = $objupdate->exec_query("COPY " . $this->dbtable . " TO '" . $dumpfile . "'");
724  $this->log->info("Dump table " . $this->dbtable . " in " . $dumpfile);
725 
726  if ($err != "") return ($err);
727  // ------------------------------
728  // second : rename table to save data
729  //$err = $objupdate-> exec_query("CREATE TABLE ".$this->dbtable."_old ( ) INHERITS (".$this->dbtable.")",1);
730  //$err = $objupdate-> exec_query("COPY ".$this->dbtable."_old FROM '".$dumpfile."'", 1 );
731  $err = $objupdate->exec_query("ALTER TABLE " . $this->dbtable . " RENAME TO " . $this->dbtable . "_old", 1);
732 
733  if ($err != "") return ($err);
734  // remove index : will be recreated in the following step (create)
735  $err = $this->exec_query("select indexname from pg_indexes where tablename='" . $this->dbtable . "_old'", 1);
736  $nbidx = $this->numrows();
737  for ($c = 0; $c < $nbidx; $c++) {
738 
739  $row = $this->fetch_array($c, PGSQL_ASSOC);
740  $err = $objupdate->exec_query("DROP INDEX " . $row["indexname"], 1);
741  }
742  // --------------------------------------------
743  // third : Create new table with new attributes
744  $this->Create(true);
745  // ---------------------------------------------------
746  // 4th : copy compatible data from old table to new table
747  $first = true;
748 
749  $this->exec_query("SELECT * FROM " . $this->dbtable . "_old");
750  $nbold = $this->numrows();
751  for ($c = 0; $c < $nbold; $c++) {
752 
753  $row = $this->fetch_array($c, PGSQL_ASSOC);
754 
755  if ($first) {
756  // compute compatible fields
757  $inter_fields = array_intersect(array_keys($row) , $this->fields);
758  reset($this->fields);
759  $fields = "(";
760  foreach ($inter_fields as $k => $v) {
761  $fields.= $v . ",";
762  }
763  $fields = substr($fields, 0, strlen($fields) - 1); // remove last comma
764  $fields.= ")";
765  $first = false;
766  }
767  // compute compatible values
768  $values = "(";
769  reset($inter_fields);
770  foreach ($inter_fields as $k => $v) {
771  $values.= "E'" . pg_escape_string($row[$v]) . "',";
772  }
773  $values = substr($values, 0, strlen($values) - 1); // remove last comma
774  $values.= ")";
775  // copy compatible values
776  $err = $objupdate->exec_query("INSERT INTO " . $this->dbtable . " " . $fields . " VALUES " . $values, 1);
777  if ($err != "") return ($err);
778  }
779  // ---------------------------------------------------
780  // 5th :delete old table (has been saved before - dump file)
781  $err = $objupdate->exec_query("DROP TABLE " . $this->dbtable . "_old", 1);
782 
783  return ($err);
784  }
785  /**
786  * set a database transaction save point
787  * @param string $point
788  * @return string error message
789  */
790  public function savePoint($point)
791  {
792  $err = '';
793  if (!self::$savepoint[$this->dbid]) {
794  self::$savepoint[$this->dbid] = array(
795  $point
796  );
797  $err = $this->exec_query("begin");
798  } else {
799  self::$savepoint[$this->dbid][] = $point;
800  }
801  if (!$err) {
802  $err = $this->exec_query(sprintf('savepoint "%s"', pg_escape_string($point)));
803  }
804  if ($err) error_log(__METHOD__ . ":$err");
805  return $err;
806  }
807  /**
808  * revert to transaction save point
809  * @param string $point
810  * @return string error message
811  */
812  public function rollbackPoint($point)
813  {
814  $lastPoint = array_search($point, self::$savepoint[$this->dbid]);
815  if ($lastPoint !== false) {
816  self::$savepoint[$this->dbid] = array_slice(self::$savepoint[$this->dbid], 0, $lastPoint);
817  $err = $this->exec_query(sprintf('rollback to savepoint "%s"', pg_escape_string($point)));
818 
819  if ((!$err) && (count(self::$savepoint[$this->dbid]) == 0)) {
820  $err = $this->exec_query("commit");
821  }
822  } else {
823 
824  $err = sprintf("cannot rollback unsaved point : %s", $point);
825  }
826 
827  if ($err) error_log(__METHOD__ . ":$err");
828  return $err;
829  }
830  /**
831  * commit transaction save point
832  * @param string $point
833  * @return string error message
834  */
835  public function commitPoint($point)
836  {
837  $lastPoint = array_search($point, self::$savepoint[$this->dbid]);
838 
839  if ($lastPoint !== false) {
840  self::$savepoint[$this->dbid] = array_slice(self::$savepoint[$this->dbid], 0, $lastPoint);
841  $err = $this->exec_query(sprintf('release savepoint "%s"', pg_escape_string($point)));
842  if ((!$err) && (count(self::$savepoint[$this->dbid]) == 0)) {
843  $err = $this->exec_query("commit");
844  }
845  } else {
846  $err = sprintf("cannot commit unsaved point : %s", $point);
847  }
848  if ($err) error_log(__METHOD__ . ":$err");
849  return $err;
850  }
851  // FIN DE CLASSE
852 
853 }
854 ?>
← centre documentaire © anakeen - published under CC License - Dynacase