Ticket #715: db_update_util.php

File db_update_util.php, 4.1 kB (added by Eric Myers, 1 year ago)

Modified do_query() to keep a log of applied database updates.

Line 
1 <?php
2 /***********************************************************************
3  * Utilities to make it easier to do a database update
4  *
5  * do_query() writes to a log file when an update is applied,
6  * and refuses to apply an update listed in the log file.
7  * Supports multiple database queries per update function.
8  *
9  * For backward compatibility you can put the names of updates you have
10  * applied by hand in the log file, without the timestamp.
11  *
12  * Eric Myers <myers@spy-hill.net> - 5 August 2008
13  * @(#) $Id: $
14 \***********************************************************************/
15
16 // Updates are recorded in the log file once they are successfully applied.
17 // We only need to locate the log file once.
18 //
19 $config_xml = get_config();
20 $config_vars = parse_element($config_xml,"<config>");
21 $log_dir = trim(parse_element($config_vars,"<log_dir>"));
22 #echo "Log directory: $log_dir \n";
23 if( !file_exists($log_dir) || !is_dir($log_dir) ){
24     die("Log file directory '$log_dir' cannot be found.\n");
25  }
26 $log_file = $log_dir ."/db_update.log";
27 #echo "Log file: $log_file \n";
28
29
30 $prev_caller="";                // name of previously attempted update
31 $update_number=0;               // to count multiple queries per update
32
33
34 // This function finds the name of the function which is applying the update.
35 //
36 function called_by($n=2){
37     $x = debug_backtrace(); // requires PHP 4.3.0 or newer
38     $y = $x[$n];
39     return $y['function'];
40 }
41
42
43 // Set descriptive text for the update.
44 // This is optional, but better than comments since it goes to log.
45 //
46 function description($text){
47     global $update_desc;
48     $update_desc = $text;
49 }
50 function describe($text){// alternate name
51     description($text);
52 } 
53
54
55 // Execute an SQL query to do the update.
56 // First check the log to see if we already did it.
57 // If not, do the update, and log it.
58 //
59 function do_query($query) {
60     global $prev_caller, $update_number;
61     global $update_desc;                // descriptive text for the update
62     global $log_file;
63
64     $caller = called_by();     // name of the update function which called us
65
66     if( $caller == $prev_caller ){ // another query for same update?
67         $update_number++;
68     }
69     else {
70         $prev_caller = $caller;
71         $update_number = 1;
72     }
73     $query_tag = "$caller($update_number)";
74
75     // Unix name of person who applied the update, for the log
76     //
77     $userinfo = posix_getpwuid(posix_getuid());
78     $username = $userinfo['name'];
79
80     // Has this update already been applied?
81     //
82     if( file_exists($log_file) ){
83         if( $fh = fopen($log_file,'r') ){
84             while( $line = fgets($fh) ){
85                 $n = strpos($line, $query_tag);
86                 if( $n !== FALSE && $n < 60) {// ignores description text
87                     echo "$query_tag has ALREADY been applied. \n";
88                     fclose($fh);
89                     return FALSE;
90                 }
91                 // Allow for just update name by itself to block update
92                 $n = strpos($line, $caller);
93                 if( ($n !== FALSE) && ($n < 25)){// only name by itself, no timestamp
94                      if($update_number==1){// but only flag the first query
95                         echo "$caller has ALREADY been applied. \n";
96                      }
97                     fclose($fh);
98                     return FALSE;
99                 }
100             }
101         }
102     }
103
104     // Try to apply the update.  If successful, write it to the log file.
105     //
106     $result = mysql_query($query);
107     #$result = true; // Debugging
108     if( !$result ){// TODO: better test for SQL errors?
109         die("$query_tag failed! \n".mysql_error());
110     }
111     else {
112         echo "$query_tag applied. \n";
113         if( !$fd=fopen($log_file, 'a') ){
114             die("CANNOT WRITE $query_tag TO LOG FILE $log_file\n");
115         }
116         else {
117             fwrite($fd, gmdate('c'). " $query_tag ");
118             if( $username ) fwrite($fd, "by $username ");
119             fwrite($fd,"$update_desc\n");
120             fclose($fd);
121             $update_desc=""; // clear the description text for next item
122         }
123     }
124 }
125
126 $cvs_version_tracker[]=        //Generated automatically - do not edit
127     "\$Id: $";
128 ?>

If this page is incomplete or incorrect, please edit it or add it to the wiki to-do list. To do this, you must be logged in; click Login or Register above.