Accept, save and show observation dates/times in vitals.
[openemr.git] / library / sql.inc
blob26f7176a9f008052946d43d840b5698232688230
1 <?php
3 include_once(dirname(__FILE__) . "/sqlconf.php");
4 require_once(dirname(__FILE__) . "/adodb/adodb.inc.php");
5 require_once(dirname(__FILE__) . "/adodb/drivers/adodb-mysql.inc.php");
7 include_once(dirname(__FILE__) . "/log.inc");
9 class ADODB_mysql_log extends ADODB_mysql
11         function Execute($sql,$inputarr=false)
12         {
13             $retval= parent::Execute($sql,$inputarr);
14             // Kevin Yeh(kevin.y@integralemr.com)
15             // Stash the insert ID into lastidado so it doesn't get clobbered when 
16             // we insert into the audit log
17             $GLOBALS['lastidado']=$this->Insert_ID();
18             $outcome= ($retval === false) ? false : true;
19             auditSQLEvent($sql,$outcome);
20             return $retval;
21         }
23         // Kevin Yeh(kevin.y@integralemr.com)
24         // Need to override this method to prevent infinite recursion with execute
25         // when trying to retrieve the last insert id.
26         function _insertid()
27         {
28             $rs=$this->ExecuteNoLog("SELECT LAST_INSERT_ID()");
29             $ret=reset($rs->fields);
30             $rs->close();
31             return $ret;
32         }
34         function ExecuteNoLog($sql,$inputarr=false)
35         {
36             return parent::Execute($sql,$inputarr);
37         }
39 if (!defined('ADODB_FETCH_ASSOC')) define('ADODB_FETCH_ASSOC', 2);
40 $database = NewADOConnection("mysql_log"); // Use the subclassed driver which logs execute events
42 $database->PConnect($host, $login, $pass, $dbase);
43 $GLOBALS['adodb']['db'] = $database;
44 $GLOBALS['dbh'] = $database->_connectionID;
46 // Modified 5/2009 by BM for UTF-8 project ---------
47 if (!$disable_utf8_flag) {
48  $success_flag = $database->Execute("SET NAMES 'utf8'");
49   if (!$success_flag) {
50    error_log("PHP custom error: from openemr library/sql.inc  - Unable to set up UTF8 encoding with mysql database: ".$database->ErrorMsg(), 0);
51   }
54 // set up associations in adodb calls (not sure why above define
55 //  command does not work)
56 $GLOBALS['adodb']['db']->SetFetchMode(ADODB_FETCH_ASSOC);
58 //fmg: This makes the login screen informative when no connection can be made
59 if (!$GLOBALS['dbh']) {
60   //try to be more helpful
61   if ($host == "localhost") {
62     echo "Check that mysqld is running.<p>";
63   } else {
64     echo "Check that you can ping the server '$host'.<p>";
65   }//if local
66   HelpfulDie("Could not connect to server!", mysql_error($GLOBALS['dbh']));
67   exit;
68 }//if no connection
71 // Function that will allow use of the adodb binding
72 //   feature to prevent sql-injection. Will continue to
73 //   be compatible with previous function calls that do
74 //   not use binding.
75 // If use adodb binding, then will return a recordset object.
76 // If do not use binding, then will return a resource object.
77 // The sqlFetchArray() function should be used to
78 //   utilize the return object (it will accept both recordset
79 //   and resource objects).
80 function sqlStatement($statement, $binds=NULL )
82   if (is_array($binds)) {
83     // Use adodb Execute with binding and return a recordset.
84     //   Note that the auditSQLEvent function is embedded
85     //    in the adodb Execute command.
86     $recordset = $GLOBALS['adodb']['db']->Execute( $statement, $binds );
87     if ($recordset === FALSE) {
88       HelpfulDie("query failed: $statement", $GLOBALS['adodb']['db']->ErrorMsg());
89     }
90     return $recordset;
91   }
92   else {
93     // Use mysql_query and return a resource.
94     $resource = mysql_query($statement, $GLOBALS['dbh']);
95     if ($resource === FALSE) {
96       auditSQLEvent($statement, FALSE);
97       HelpfulDie("query failed: $statement", mysql_error($GLOBALS['dbh']));
98     }
99     auditSQLEvent($statement, TRUE);
100     return $resource;
101   }
104 // Function that will allow use of the adodb binding
105 //   feature to prevent sql-injection.
106 // It will act upon the object returned from the 
107 //   sqlStatement() function (and sqlQ() function).
108 // It will automatically figure out if the input
109 //   object is a recordset or a resource.
110 function sqlFetchArray($r)
112   if (!is_resource($r)) {
113     //treat as an adodb recordset
114     if ($r === FALSE)
115       return false;
116     if ($r->EOF)
117       return false;
118     //ensure it's an object (ie. is set)
119     if (!is_object($r))
120       return false;
121     return $r->FetchRow();
122   }
123   else {
124     //treat as a mysql_query resource
125     if ($r == FALSE)
126       return false;
127     return mysql_fetch_array($r, MYSQL_ASSOC);
128   }
131 // Function that will allow use of the adodb binding
132 //   feature to prevent sql-injection.
133 // This function is specialized for insert functions
134 //   and will return the last id generated from the
135 //   insert.
136 function sqlInsert($statement, $binds=array())
138   //Run a adodb execute
139   // Note the auditSQLEvent function is embedded in the
140   //   adodb Execute function.
141   $recordset = $GLOBALS['adodb']['db']->Execute($statement, $binds);
142   if ($recordset === FALSE) {
143     HelpfulDie("insert failed: $statement", $GLOBALS['adodb']['db']->ErrorMsg());
144   }
145   // Return the correct last id generated using function
146   //   that is safe with the audit engine.
147   return getSqlLastID();
150 // Function that will allow use of the adodb binding
151 //   feature to prevent sql-injection.
152 // This function is specialized for simply returning
153 //   the first row of a query as an associative array.
154 // The $status_or_binds parameter can do following:
155 //   FALSE or an array() - Run adodb Execute with binding,
156 //     if applicable.
157 //   TRUE - run mysql_query for a specific case in the audit engine
158 //     (library/log.inc) to skip auditing and reporting if the query
159 //     does not work.
160 function sqlQuery($statement, $status_or_binds=FALSE)
162   if ((is_array($status_or_binds)) || ($status_or_binds === FALSE)) {
163     // run the adodb Execute function
164     //   Note the auditSQLEvent function is embedded in the
165     //     adodb Execute function.
166     if (is_array($status_or_binds)) {
167       $recordset = $GLOBALS['adodb']['db']->Execute( $statement, $status_or_binds );
168     }
169     else {
170       $recordset = $GLOBALS['adodb']['db']->Execute( $statement );
171     }
172     if ($recordset === FALSE) {
173       HelpfulDie("query failed: $statement", $GLOBALS['adodb']['db']->ErrorMsg());
174     }
175     if ($recordset->EOF)
176      return FALSE;
177     $rez = $recordset->FetchRow();
178     if ($rez == FALSE)
179       return FALSE;
180     return $rez;
181   }
182   else {
183     // run mysql_query to bypass the audit engine if error
184     //   in query.
185     $resource = mysql_query($statement, $GLOBALS['dbh']);
186     auditSQLEvent($statement, TRUE);
187    //$rez = @mysql_fetch_array($query, MYSQL_ASSOC);
188     $rez = @mysql_fetch_array($resource, MYSQL_ASSOC); //Replace $query with $resource to calculate correct checksum
189     if ($rez == FALSE)
190       return FALSE;
191     return $rez;
192   }
195 // ViSolve: Create a seperate function for audit log calls.
196 /* Kevin Yeh (kevin.y@integralemr.com) 12/13/2011
197  * This allows us to insert a row in the log table that doesn't log its own actions.
198  */
199 function sqlInsertClean_audit($statement)
202   $ret = $GLOBALS['adodb']['db']->ExecuteNoLog($statement);
203   if ($ret === FALSE) {
204     HelpfulDie("insert failed: $statement", $GLOBALS['adodb']['db']->ErrorMsg());
205   }
208 // Function that will safely return the last
209 //   ID inserted, and accounts for
210 //   the audit engine.
211 function getSqlLastID() {
212   if ($GLOBALS['lastidado'] >0) {
213     return $GLOBALS['lastidado'];
214   }
215   else {
216     return $GLOBALS['adodb']['db']->Insert_ID();
217   }
220 // Function that will return an array listing
221 //   of columns that exist in a table.
222 function sqlListFields($table) {
223   $sql = "SHOW COLUMNS FROM ". mysql_real_escape_string($table);
224   $resource = sqlQ($sql);
225   $field_list = array();
226   while($row = mysql_fetch_array($resource)) {
227     $field_list[] = $row['Field'];
228   }
229   return $field_list;
232 // Function that will allow use of the adodb binding
233 //   feature to prevent sql-injection.
234 // It will act upon the object returned from the
235 //   sqlStatement() function (and sqlQ() function).
236 // It will automatically figure out if the input
237 //   object is a recordset or a resource.
238 // It will return the number of rows.
239 function sqlNumRows($r)
241   if (!is_resource($r)) {
242     //treat as an adodb recordset
243     return $r->RecordCount();
244   }
245   else {
246     //treat as a mysql_query resource
247     return mysql_num_rows($r);
248   }
251 //fmg: Much more helpful that way...
252 function HelpfulDie ($statement, $sqlerr='')
254   echo "<p><p><font color='red'>ERROR:</font> $statement<p>";
255   if ($sqlerr) {
256     echo "Error: <font color='red'>$sqlerr</font><p>";
257   }//if error
258   exit;
261 function generate_id () {
262   $database = $GLOBALS['adodb']['db'];
263   return $database->GenID("sequences");
266 // Does not fully incorporate the audit engine, so
267 //   recommend not using this function (if bind is set,
268 //   then will get logged, however if bind is not set,
269 //   then will not get logged).  
270 // Function that will allow use of the adodb binding
271 //   feature to prevent sql-injection.
272 // Function that will allow use of the adodb binding
273 //   feature to prevent sql-injection. Will continue to
274 //   be compatible with previous function calls that do
275 //   not use binding.
276 // If use adodb binding, then will return a recordset object.
277 // If do not use binding, then will return a resource object.
278 // The sqlFetchArray() function should be used to
279 //   utilize the return object (it will accept both recordset
280 //   and resource objects).
281 function sqlQ($statement, $binds=NULL )
283   if (is_array($binds)) {
284     $recordset = $GLOBALS['adodb']['db']->Execute( $statement, $binds ) or
285       HelpfulDie("query failed: $statement", $GLOBALS['adodb']['db']->ErrorMsg());
286     return $recordset;
287   }
288   else {
289     $resource = mysql_query($statement, $GLOBALS['dbh']) or
290       HelpfulDie("query failed: $statement", mysql_error($GLOBALS['dbh']));
291     return $resource;
292   }
295 // DEPRECATED FUNCTION
297 // Function that will allow use of the adodb binding
298 //   feature to prevent sql-injection.
299 // A simple wrapper for the sqlInsert() function.
300 function idSqlStatement($statement , $binds=NULL )
302   return sqlInsert($statement, $binds);
305 // DEPRECATED FUNCTION
307 // Function that will allow use of the adodb binding
308 //   feature to prevent sql-injection.
309 // A simple wrapper for the sqlInsert() function.
310 function sqlInsertClean($statement, $binds=NULL )
312   return sqlInsert($statement, $binds);
315 // DEPRECATED FUNCTION
316 function sqlConnect($login,$pass,$dbase,$host,$port = '3306')
318   $GLOBALS['dbh'] = $database->_connectionID;
319   return $GLOBALS['dbh'];
322 // DEPRECATED FUNCTION
324 // Function to close the connection. PHP does
325 //   this automatically, so not needed.
326 function sqlClose()
328   //----------Close our mysql connection
329   $closed = $GLOBALS['adodb']['db']->close or
330     HelpfulDie("could not disconnect from mysql server link", $GLOBALS['adodb']['db']->ErrorMsg());
331   return $closed;
334 // DEPRECATED FUNCTION
335 function get_db() {
336   return $GLOBALS['adodb']['db'];