fix and chore: pinned maennchen/zipstream-php version to work with arm7 and updated...
[openemr.git] / library / sql.inc.php
blob4fee883d7de3af0641e10a29fb786c3e624b1b2a
1 <?php
3 /**
4 * Sql functions/classes for OpenEMR.
6 * Includes classes and functions that OpenEMR uses
7 * to interact with SQL.
9 * @package OpenEMR
10 * @link http://www.open-emr.org
11 * @author Brady Miller <brady.g.miller@gmail.com>
12 * @author Kevin Yeh <kevin.y@integralemr.com>
13 * @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
14 * @copyright Copyright (c) 2013 Kevin Yeh <kevin.y@integralemr.com>
15 * @copyright Copyright (c) 2013 OEMR <www.oemr.org>
16 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
19 require_once(dirname(__FILE__) . "/sqlconf.php");
20 require_once(dirname(__FILE__) . "/../vendor/adodb/adodb-php/adodb.inc.php");
21 require_once(dirname(__FILE__) . "/../vendor/adodb/adodb-php/drivers/adodb-mysqli.inc.php");
22 require_once(dirname(__FILE__) . "/ADODB_mysqli_log.php");
24 if (!defined('ADODB_FETCH_ASSOC')) {
25 define('ADODB_FETCH_ASSOC', 2);
28 $database = NewADOConnection("mysqli_log"); // Use the subclassed driver which logs execute events
29 // Below optionFlags flag is telling the mysql connection to ensure local_infile setting,
30 // which is needed to import data in the Administration->Other->External Data Loads feature.
31 // (Note the MYSQLI_READ_DEFAULT_GROUP is just to keep the current setting hard-coded in adodb)
32 $database->setConnectionParameter(MYSQLI_READ_DEFAULT_GROUP, 0);
33 $database->setConnectionParameter(MYSQLI_OPT_LOCAL_INFILE, 1);
34 // Set mysql to use ssl, if applicable.
35 // Can support basic encryption by including just the mysql-ca pem (this is mandatory for ssl)
36 // Can also support client based certificate if also include mysql-cert and mysql-key (this is optional for ssl)
37 if (file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-ca")) {
38 if (defined('MYSQLI_CLIENT_SSL')) {
39 if (
40 file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-key") &&
41 file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-cert")
42 ) {
43 // with client side certificate/key
44 $database->ssl_key = "{$GLOBALS['OE_SITE_DIR']}/documents/certificates/mysql-key";
45 $database->ssl_cert = "{$GLOBALS['OE_SITE_DIR']}/documents/certificates/mysql-cert";
46 $database->ssl_ca = "{$GLOBALS['OE_SITE_DIR']}/documents/certificates/mysql-ca";
47 } else {
48 // without client side certificate/key
49 $database->ssl_ca = "{$GLOBALS['OE_SITE_DIR']}/documents/certificates/mysql-ca";
51 $database->clientFlags = MYSQLI_CLIENT_SSL;
54 $database->port = $port;
55 if ((!empty($GLOBALS["enable_database_connection_pooling"]) || !empty($_SESSION["enable_database_connection_pooling"])) && empty($GLOBALS['connection_pooling_off'])) {
56 $database->PConnect($host, $login, $pass, $dbase);
57 } else {
58 $database->connect($host, $login, $pass, $dbase);
60 $GLOBALS['adodb']['db'] = $database;
61 $GLOBALS['dbh'] = $database->_connectionID;
63 // Modified 5/2009 by BM for UTF-8 project ---------
64 if (!$disable_utf8_flag) {
65 if (!empty($sqlconf["db_encoding"]) && ($sqlconf["db_encoding"] == "utf8mb4")) {
66 $success_flag = $database->ExecuteNoLog("SET NAMES 'utf8mb4'");
67 if (!$success_flag) {
68 error_log("PHP custom error: from openemr library/sql.inc.php - Unable to set up UTF8MB4 encoding with mysql database: " . errorLogEscape(getSqlLastError()), 0);
70 } else {
71 $success_flag = $database->ExecuteNoLog("SET NAMES 'utf8'");
72 if (!$success_flag) {
73 error_log("PHP custom error: from openemr library/sql.inc.php - Unable to set up UTF8 encoding with mysql database: " . errorLogEscape(getSqlLastError()), 0);
78 // Turn off STRICT SQL
79 $sql_strict_set_success = $database->ExecuteNoLog("SET sql_mode = ''");
80 if (!$sql_strict_set_success) {
81 error_log("Unable to set strict sql setting: " . errorLogEscape(getSqlLastError()), 0);
84 // set up associations in adodb calls (not sure why above define
85 // command does not work)
86 $GLOBALS['adodb']['db']->SetFetchMode(ADODB_FETCH_ASSOC);
88 if (!empty($GLOBALS['debug_ssl_mysql_connection'])) {
89 error_log("CHECK SSL CIPHER IN MAIN ADODB: " . errorLogEscape(print_r($GLOBALS['adodb']['db']->ExecuteNoLog("SHOW STATUS LIKE 'Ssl_cipher';")->fields, true)));
92 //fmg: This makes the login screen informative when no connection can be made
93 if (!$GLOBALS['dbh']) {
94 //try to be more helpful
95 if ($host == "localhost") {
96 echo "Check that mysqld is running.<p>";
97 } else {
98 echo "Check that you can ping the server " . text($host) . ".<p>";
99 }//if local
100 HelpfulDie("Could not connect to server!", getSqlLastError());
101 exit;
102 }//if no connection
105 * Standard sql query in OpenEMR.
107 * Function that will allow use of the adodb binding
108 * feature to prevent sql-injection. Will continue to
109 * be compatible with previous function calls that do
110 * not use binding.
111 * It will return a recordset object.
112 * The sqlFetchArray() function should be used to
113 * utilize the return object.
115 * @param string $statement query
116 * @param array $binds binded variables array (optional)
117 * @return recordset
119 function sqlStatement($statement, $binds = false)
121 // Below line is to avoid a nasty bug in windows.
122 if (empty($binds)) {
123 $binds = false;
126 // Use adodb Execute with binding and return a recordset.
127 // Note that the auditSQLEvent function is embedded
128 // in the Execute command.
129 $recordset = $GLOBALS['adodb']['db']->Execute($statement, $binds);
130 if ($recordset === false) {
131 HelpfulDie("query failed: $statement", getSqlLastError());
134 return $recordset;
138 * Standard sql query in OpenEMR.
140 * Function that will allow use of the adodb binding
141 * feature to prevent sql-injection. Will continue to
142 * be compatible with previous function calls that do
143 * not use binding.
144 * It will return a recordset object.
145 * The sqlFetchArray() function should be used to
146 * utilize the return object.
148 * @param string $statement query
149 * @param array $binds binded variables array (optional)
150 * @return recordset
152 function sqlStatementThrowException($statement, $binds = false)
154 // Below line is to avoid a nasty bug in windows.
155 if (empty($binds)) {
156 $binds = false;
159 //Run a adodb execute
160 // Note the auditSQLEvent function is embedded in the
161 // Execute function.
162 $recordset = $GLOBALS['adodb']['db']->Execute($statement, $binds, true);
163 if ($recordset === false) {
164 throw new \OpenEMR\Common\Database\SqlQueryException($statement, "Failed to execute statement. Error: " . getSqlLastError() . " Statement: " . $statement);
166 return $recordset;
170 * Return the last inserted sql id for a query.
171 * @return int
173 function sqlGetLastInsertId()
175 // Return the correct last id generated using function
176 // that is safe with the audit engine.
177 return $GLOBALS['lastidado'] > 0 ? $GLOBALS['lastidado'] : $GLOBALS['adodb']['db']->Insert_ID();
181 * Specialized sql query in OpenEMR that skips auditing.
183 * Function that will allow use of the adodb binding
184 * feature to prevent sql-injection. Will continue to
185 * be compatible with previous function calls that do
186 * not use binding. It is equivalent to the
187 * sqlStatement() function, EXCEPT it skips the
188 * audit engine. This function should only be used
189 * in very special situations.
190 * It will return a recordset object.
191 * The sqlFetchArray() function should be used to
192 * utilize the return object.
194 * @param string $statement query
195 * @param array $binds binded variables array (optional)
196 * @return recordset
198 function sqlStatementNoLog($statement, $binds = false, $throw_exception_on_error = false)
200 // Below line is to avoid a nasty bug in windows.
201 if (empty($binds)) {
202 $binds = false;
205 // Use adodb ExecuteNoLog with binding and return a recordset.
206 $recordset = $GLOBALS['adodb']['db']->ExecuteNoLog($statement, $binds);
207 if ($recordset === false) {
208 if ($throw_exception_on_error) {
209 throw new \OpenEMR\Common\Database\SqlQueryException($statement, "Failed to execute statement. Error: " . getSqlLastError() . " Statement: " . $statement);
210 } else {
211 HelpfulDie("query failed: $statement", getSqlLastError());
215 return $recordset;
219 * sqlStatement() function wrapper for CDR engine in OpenEMR.
220 * Allows option to turn on/off auditing specifically for the
221 * CDR engine.
223 * @param string $statement query
224 * @param array $binds binded variables array (optional)
225 * @return recordset/resource
227 function sqlStatementCdrEngine($statement, $binds = false)
229 // Below line is to avoid a nasty bug in windows.
230 if (empty($binds)) {
231 $binds = false;
234 if ($GLOBALS['audit_events_cdr']) {
235 return sqlStatement($statement, $binds);
236 } else {
237 return sqlStatementNoLog($statement, $binds);
242 * Returns a row (as an array) from a sql recordset.
244 * Function that will allow use of the adodb binding
245 * feature to prevent sql-injection.
246 * It will act upon the object returned from the
247 * sqlStatement() function (and sqlQ() function).
249 * @param recordset $r
250 * @return array
252 function sqlFetchArray($r)
254 //treat as an adodb recordset
255 if ($r === false) {
256 return false;
259 if ($r->EOF ?? '') {
260 return false;
263 //ensure it's an object (ie. is set)
264 if (!is_object($r)) {
265 return false;
268 return $r->FetchRow();
273 * Wrapper for ADODB getAssoc
275 * @see http://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:getassoc
277 * @param string $sql
278 * @param string[] $bindvars
279 * @param boolean $forceArray
280 * @param boolean $first2Cols
281 * @return array
283 function sqlGetAssoc($sql, $bindvars = false, $forceArray = false, $first2Cols = false)
286 return $GLOBALS['adodb']['db']->getAssoc($sql, $bindvars, $forceArray, $first2Cols);
290 * Standard sql insert query in OpenEMR.
291 * Only use this function if you need to have the
292 * id returned. If doing an insert query and do
293 * not need the id returned, then use the
294 * sqlStatement function instead.
296 * Function that will allow use of the adodb binding
297 * feature to prevent sql-injection. This function
298 * is specialized for insert function and will return
299 * the last id generated from the insert.
301 * @param string $statement query
302 * @param array $binds binded variables array (optional)
303 * @return integer Last id generated from the sql insert command
305 function sqlInsert($statement, $binds = false)
307 // Below line is to avoid a nasty bug in windows.
308 if (empty($binds)) {
309 $binds = false;
312 //Run a adodb execute
313 // Note the auditSQLEvent function is embedded in the
314 // Execute function.
315 $recordset = $GLOBALS['adodb']['db']->Execute($statement, $binds, true);
316 if ($recordset === false) {
317 HelpfulDie("insert failed: $statement", getSqlLastError());
320 // Return the correct last id generated using function
321 // that is safe with the audit engine.
322 return $GLOBALS['lastidado'] > 0 ? $GLOBALS['lastidado'] : $GLOBALS['adodb']['db']->Insert_ID();
326 * Specialized sql query in OpenEMR that only returns
327 * the first row of query results as an associative array.
329 * Function that will allow use of the adodb binding
330 * feature to prevent sql-injection.
332 * @param string $statement query
333 * @param array $binds binded variables array (optional)
334 * @return array
336 function sqlQuery($statement, $binds = false)
338 // Below line is to avoid a nasty bug in windows.
339 if (empty($binds)) {
340 $binds = false;
343 $recordset = $GLOBALS['adodb']['db']->Execute($statement, $binds);
345 if ($recordset === false) {
346 HelpfulDie("query failed: $statement", getSqlLastError());
349 if ($recordset->EOF) {
350 return false;
353 $rez = $recordset->FetchRow();
354 if ($rez == false) {
355 return false;
358 return $rez;
362 * Specialized sql query in OpenEMR that bypasses the auditing engine
363 * and only returns the first row of query results as an associative array.
365 * Function that will allow use of the adodb binding
366 * feature to prevent sql-injection. It is equivalent to the
367 * sqlQuery() function, EXCEPT it skips the
368 * audit engine. This function should only be used
369 * in very special situations.
371 * Note: If you do an INSERT or UPDATE statement you will get an empty string ("") as a response
373 * @param string $statement query
374 * @param array $binds binded variables array (optional)
375 * @return array|false|""
377 function sqlQueryNoLog($statement, $binds = false, $throw_exception_on_error = false)
379 // Below line is to avoid a nasty bug in windows.
380 if (empty($binds)) {
381 $binds = false;
384 $recordset = $GLOBALS['adodb']['db']->ExecuteNoLog($statement, $binds);
386 if ($recordset === false) {
387 if ($throw_exception_on_error) {
388 throw new \OpenEMR\Common\Database\SqlQueryException($statement, "Failed to execute statement. Error: " . getSqlLastError() . " Statement: " . $statement);
389 } else {
390 HelpfulDie("query failed: $statement", getSqlLastError());
394 if ($recordset->EOF) {
395 return false;
398 $rez = $recordset->FetchRow();
399 if ($rez == false) {
400 return false;
403 return $rez;
407 * Specialized sql query in OpenEMR that ignores sql errors, bypasses the
408 * auditing engine and only returns the first row of query results as an
409 * associative array.
411 * Function that will allow use of the adodb binding
412 * feature to prevent sql-injection. It is equivalent to the
413 * sqlQuery() function, EXCEPT it skips the
414 * audit engine and ignores erros. This function should only be used
415 * in very special situations.
417 * @param string $statement query
418 * @param array $binds binded variables array (optional)
419 * @return array
421 function sqlQueryNoLogIgnoreError($statement, $binds = false)
423 // Below line is to avoid a nasty bug in windows.
424 if (empty($binds)) {
425 $binds = false;
428 $recordset = $GLOBALS['adodb']['db']->ExecuteNoLog($statement, $binds);
430 if ($recordset === false) {
431 // ignore the error and return FALSE
432 return false;
435 if ($recordset->EOF) {
436 return false;
439 $rez = $recordset->FetchRow();
440 if ($rez == false) {
441 return false;
444 return $rez;
448 * sqlQuery() function wrapper for CDR engine in OpenEMR.
449 * Allows option to turn on/off auditing specifically for the
450 * CDR engine.
452 * @param string $statement query
453 * @param array $binds binded variables array (optional)
454 * @return array
456 function sqlQueryCdrEngine($statement, $binds = false)
458 // Below line is to avoid a nasty bug in windows.
459 if (empty($binds)) {
460 $binds = false;
463 if ($GLOBALS['audit_events_cdr']) {
464 return sqlQuery($statement, $binds);
465 } else {
466 return sqlQueryNoLog($statement, $binds);
471 * Specialized sql query in OpenEMR that skips auditing.
473 * This function should only be used in very special situations.
475 * @param string $statement query
477 function sqlInsertClean_audit($statement, $binds = false)
479 // Below line is to avoid a nasty bug in windows.
480 if (empty($binds)) {
481 $binds = false;
484 $ret = $GLOBALS['adodb']['db']->ExecuteNoLog($statement, $binds);
485 if ($ret === false) {
486 HelpfulDie("insert failed: $statement", getSqlLastError());
491 * Function that will safely return the last error,
492 * and accounts for the audit engine.
494 * @param string $mode either adodb(default) or native_mysql
495 * @return string last mysql error
497 function getSqlLastError()
499 return !empty($GLOBALS['last_mysql_error']) ? $GLOBALS['last_mysql_error'] : $GLOBALS['adodb']['db']->ErrorMsg();
503 * Function that will safely return the last error no,
504 * and accounts for the audit engine.
506 * @param string $mode either adodb(default) or native_mysql
507 * @return string last mysql error no
509 function getSqlLastErrorNo()
511 return !empty($GLOBALS['last_mysql_error_no']) ? $GLOBALS['last_mysql_error_no'] : $GLOBALS['adodb']['db']->ErrorNo();
515 * Function that will return an array listing
516 * of columns that exist in a table.
518 * @param string $table sql table
519 * @return array
521 function sqlListFields($table)
523 $sql = "SHOW COLUMNS FROM " . add_escape_custom($table);
524 $resource = sqlStatementNoLog($sql);
525 $field_list = array();
526 while ($row = sqlFetchArray($resource)) {
527 $field_list[] = $row['Field'];
530 return $field_list;
534 * Returns the number of sql rows
536 * @param recordset $r
537 * @return integer Number of rows
539 function sqlNumRows($r)
541 return $r->RecordCount();
545 * Error function for OpenEMR sql functions
547 * @param string $statement
548 * @param string $sqlerr
550 function HelpfulDie($statement, $sqlerr = '')
553 echo "<h2><font color='red'>" . xlt('Query Error') . "</font></h2>";
555 if (!$GLOBALS['sql_string_no_show_screen']) {
556 echo "<p><font color='red'>ERROR:</font> " . text($statement) . "</p>";
559 $logMsg = "SQL Error with statement:" . $statement;
561 if ($sqlerr) {
562 if (!$GLOBALS['sql_string_no_show_screen']) {
563 echo "<p>Error: <font color='red'>" . text($sqlerr) . "</font></p>";
566 $logMsg .= "--" . $sqlerr;
567 }//if error
569 $backtrace = debug_backtrace();
571 if (!$GLOBALS['sql_string_no_show_screen']) {
572 for ($level = 1; $level < count($backtrace); $level++) {
573 $info = $backtrace[$level];
574 echo "<br />" . text($info["file"] . " at " . $info["line"] . ":" . $info["function"]);
575 if ($level > 1) {
576 echo "(" . text(implode(",", $info["args"])) . ")";
581 $logMsg .= "==>" . $backtrace[1]["file"] . " at " . $backtrace[1]["line"] . ":" . $backtrace[1]["function"];
583 error_log(errorLogEscape($logMsg));
585 exit;
589 * Function provides generation of sequence numbers with built-in ADOdb function.
590 * Increments the number in the sequences table.
591 * One example of use is the counter for form_id in the forms table.
593 * @return integer
595 function generate_id()
597 $database = $GLOBALS['adodb']['db'];
598 return $database->GenID("sequences");
602 * Deprecated function. Standard sql query in OpenEMR.
604 * Function that will allow use of the adodb binding
605 * feature to prevent sql-injection. Will continue to
606 * be compatible with previous function calls that do
607 * not use binding.
608 * It will return a recordset object.
609 * The sqlFetchArray() function should be used to
610 * utilize the return object.
612 * @deprecated
613 * @param string $statement query
614 * @param array $binds binded variables array (optional)
615 * @return recordset
617 function sqlQ($statement, $binds = false)
619 // Below line is to avoid a nasty bug in windows.
620 if (empty($binds)) {
621 $binds = false;
624 $recordset = $GLOBALS['adodb']['db']->Execute($statement, $binds) or
625 HelpfulDie("query failed: $statement", getSqlLastError());
626 return $recordset;
631 * Sql close connection function (deprecated)
633 * No longer needed since PHP does this automatically.
635 * @deprecated
636 * @return boolean
638 function sqlClose()
640 //----------Close our mysql connection
641 $closed = $GLOBALS['adodb']['db']->close or
642 HelpfulDie("could not disconnect from mysql server link", getSqlLastError());
643 return $closed;
647 * Very simple wrapper function and not necessary (deprecated)
649 * Do not use.
651 * @deprecated
652 * @return connection
654 function get_db()
656 return $GLOBALS['adodb']['db'];
660 * Generic mysql select db function
661 * Used when converted to mysqli to centralize special circumstances.
662 * @param string $database
664 function generic_sql_select_db($database, $link = null)
666 if (is_null($link)) {
667 $link = $GLOBALS['dbh'];
670 mysqli_select_db($link, $database);
674 * Generic mysql affected rows function
675 * Used when converted to mysqli to centralize special circumstances.
678 function generic_sql_affected_rows()
680 return $GLOBALS['adodb']['db']->affected_rows();
684 * Generic mysql insert id function
685 * Used when converted to mysqli to centralize special circumstances.
688 function generic_sql_insert_id()
690 return mysqli_insert_id($GLOBALS['dbh']);
695 * Begin a Transaction.
697 function sqlBeginTrans()
699 $GLOBALS['adodb']['db']->BeginTrans();
704 * Commit a transaction
706 function sqlCommitTrans($ok = true)
708 $GLOBALS['adodb']['db']->CommitTrans();
713 * Rollback a transaction
715 function sqlRollbackTrans()
717 $GLOBALS['adodb']['db']->RollbackTrans();
721 * For the 3 functions below:
723 * To support an optional higher level of security, queries that access password
724 * related information use these functions instead of the standard functions
725 * provided by sql.inc.php.
727 * By default, the privQuery and privStatement calls pass-through to
728 * the existing ADODB instance initialized by sql.inc.php.
730 * If an additional configuration file is created (secure_sqlconf.php) and saved
731 * in the sites/<sitename> directory (e.g. sites/default). The MySQL login
732 * information defined in that file as $secure_* will be used to create an ADODB
733 * instance specifically for querying privileged information.
735 * By configuring a server in this way, the default MySQL user can be denied access
736 * to sensitive tables (currently only "users_secure" would qualify). Thus
737 * the likelyhood of unintended modification can be reduced (e.g. through SQL Injection).
739 * Details on how to set this up are included in Documentation/privileged_db/priv_db_HOWTO
741 * The trade off for this additional security is extra complexity in configuration and
742 * maintenance of the database, hence it is not enabled at install time and must be
743 * done manually.
746 function getPrivDB()
748 if (!isset($GLOBALS['PRIV_DB'])) {
749 $secure_config = $GLOBALS['OE_SITE_DIR'] . "/secure_sqlconf.php";
750 if (file_exists($secure_config)) {
751 require_once($secure_config);
752 $GLOBALS['PRIV_DB'] = NewADOConnection("mysqli_log"); // Use the subclassed driver which logs execute events
753 // Below optionFlags flag is telling the mysql connection to ensure local_infile setting,
754 // which is needed to import data in the Administration->Other->External Data Loads feature.
755 // (Note the MYSQLI_READ_DEFAULT_GROUP is just to keep the current setting hard-coded in adodb)
756 $GLOBALS['PRIV_DB']->setConnectionParameter(MYSQLI_READ_DEFAULT_GROUP, 0);
757 $GLOBALS['PRIV_DB']->setConnectionParameter(MYSQLI_OPT_LOCAL_INFILE, 1);
758 // Set mysql to use ssl, if applicable.
759 // Can support basic encryption by including just the mysql-ca pem (this is mandatory for ssl)
760 // Can also support client based certificate if also include mysql-cert and mysql-key (this is optional for ssl)
761 if (file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-ca")) {
762 if (defined('MYSQLI_CLIENT_SSL')) {
763 if (
764 file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-key") &&
765 file_exists($GLOBALS['OE_SITE_DIR'] . "/documents/certificates/mysql-cert")
767 // with client side certificate/key
768 $GLOBALS['PRIV_DB']->ssl_key = "{$GLOBALS['OE_SITE_DIR']}/documents/certificates/mysql-key";
769 $GLOBALS['PRIV_DB']->ssl_cert = "{$GLOBALS['OE_SITE_DIR']}/documents/certificates/mysql-cert";
770 $GLOBALS['PRIV_DB']->ssl_ca = "{$GLOBALS['OE_SITE_DIR']}/documents/certificates/mysql-ca";
771 } else {
772 // without client side certificate/key
773 $GLOBALS['PRIV_DB']->ssl_ca = "{$GLOBALS['OE_SITE_DIR']}/documents/certificates/mysql-ca";
775 $GLOBALS['PRIV_DB']->clientFlags = MYSQLI_CLIENT_SSL;
778 $GLOBALS['PRIV_DB']->port = $port;
779 if ((!empty($GLOBALS["enable_database_connection_pooling"]) || !empty($_SESSION["enable_database_connection_pooling"])) && empty($GLOBALS['connection_pooling_off'])) {
780 $GLOBALS['PRIV_DB']->PConnect($secure_host, $secure_login, $secure_pass, $secure_dbase);
781 } else {
782 $GLOBALS['PRIV_DB']->connect($secure_host, $secure_login, $secure_pass, $secure_dbase);
784 // set up associations in adodb calls
785 $GLOBALS['PRIV_DB']->SetFetchMode(ADODB_FETCH_ASSOC);
786 // debug hook for ssl stuff
787 if (!empty($GLOBALS['debug_ssl_mysql_connection'])) {
788 error_log("CHECK SSL CIPHER IN PRIV_DB ADODB: " . errorLogEscape(print_r($GLOBALS[PRIV_DB]->ExecuteNoLog("SHOW STATUS LIKE 'Ssl_cipher';")->fields), true));
790 } else {
791 $GLOBALS['PRIV_DB'] = $GLOBALS['adodb']['db'];
795 return $GLOBALS['PRIV_DB'];
798 * mechanism to use "super user" for SQL queries related to password operations
800 * @param type $sql
801 * @param type $params
802 * @return type
804 function privStatement($sql, $params = null)
806 if (is_array($params)) {
807 $recordset = getPrivDB()->ExecuteNoLog($sql, $params);
808 } else {
809 $recordset = getPrivDB()->ExecuteNoLog($sql);
812 if ($recordset === false) {
813 // These error messages are explictly NOT run through xl() because we still
814 // need them if there is a database problem.
815 echo "Failure during database access! Check server error log.";
816 $backtrace = debug_backtrace();
818 error_log("Executing as user:" . errorLogEscape(getPrivDB()->user) . " Statement failed:" . errorLogEscape($sql) . ":" . errorLogEscape($GLOBALS['last_mysql_error'])
819 . "==>" . errorLogEscape($backtrace[1]["file"]) . " at " . errorLogEscape($backtrace[1]["line"]) . ":" . errorLogEscape($backtrace[1]["function"]));
820 exit;
823 return $recordset;
827 * Wrapper for privStatement that just returns the first row of a query or FALSE
828 * if there were no results.
830 * @param type $sql
831 * @param type $params
832 * @return boolean
834 function privQuery($sql, $params = null)
836 $recordset = privStatement($sql, $params);
837 if ($recordset->EOF) {
838 return false;
841 $rez = $recordset->FetchRow();
842 if ($rez == false) {
843 return false;
846 return $rez;
851 * Function provides generation of sequence numbers with built-in ADOdb function.
852 * Increments the number in the edi_sequences table.
853 * One example of use is the counter for batches in the 837 claims creation.
855 * @return integer
857 function edi_generate_id()
859 $database = $GLOBALS['adodb']['db'];
860 return $database->GenID("edi_sequences");