2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
39 include_once('include/database/MssqlManager.php');
41 class FreeTDSManager extends MssqlManager
44 public $isFreeTDS = true;
47 * @see DBManager::query()
49 public function query(
56 $sql = $this->appendN($sql);
57 parent::countQuery($sql);
58 $GLOBALS['log']->info('Query:' . $sql);
59 $this->checkConnection();
60 $this->query_time = microtime(true);
65 $result = @mssql_query($sql,$this->database);
70 // awu Bug 10657: ignoring mssql error message 'Changed database context to' - an intermittent
71 // and difficult to reproduce error. The message is only a warning, and does
72 // not affect the functionality of the query
73 $sqlmsg = mssql_get_last_message();
74 $sqlpos = strpos($sqlmsg, 'Changed database context to');
77 if ($sqlpos !== false)
78 // if sqlmsg has 'Changed database context to', just log it
79 $GLOBALS['log']->debug(mssql_get_last_message() . ": " . $sql );
81 $GLOBALS['log']->fatal('SQL Error : ' . mssql_get_last_message());
82 sugar_die($GLOBALS['app_strings']['ERR_DB_FAIL']);
85 echo 'SQL Error : ' . mssql_get_last_message();
87 $GLOBALS['log']->fatal(mssql_get_last_message() . ": " . $sql );
89 $this->lastmysqlrow = -1;
91 $this->query_time = microtime(true) - $this->query_time;
92 $GLOBALS['log']->info('Query Execution Time:'.$this->query_time);
95 $this->checkError($msg.' Query Failed:' . $sql, $dieOnError);
102 * This is a utility function to prepend the "N" character in front of SQL values that are
103 * surrounded by single quotes.
105 * @param $sql string SQL statement
106 * @return string SQL statement with single quote values prepended with "N" character for nvarchar columns
108 public function appendN(
112 // If there are no single quotes, don't bother, will just assume there is no character data
113 if (strpos($sql, '\'') === false)
116 $sql = str_replace('\\\'', '<@#@#@ESCAPED_QUOTE@#@#@>', $sql);
118 //The only location of three subsequent ' will be at the begning or end of a value.
119 $sql = preg_replace('/(?<!\')(\'{3})(?!\')/', "'<@#@#@PAIR@#@#@>", $sql);
121 // Flag if there are odd number of single quotes, just continue w/o trying to append N
122 if ((substr_count($sql, '\'') & 1)) {
123 $GLOBALS['log']->error('SQL statement[' . $sql . '] has odd number of single quotes.');
127 // Remove any remaining '' and do not parse... replace later (hopefully we don't even have any)
129 $regexp = '/(\'{2})/';
130 $pair_matches = array();
131 preg_match_all($regexp, $sql, $pair_matches);
133 foreach (array_unique($pair_matches[0]) as $key=>$value) {
134 $pairs['<@PAIR-'.$key.'@>'] = $value;
136 if (!empty($pairs)) {
137 $sql = str_replace($pairs, array_keys($pairs), $sql);
141 $regexp = "/(N?\'.+?\')/is";
143 preg_match_all($regexp, $sql, $matches);
145 if (!empty($matches)) {
146 foreach ($matches[0] as $key=>$value) {
147 // We are assuming that all nvarchar columns are no more than 200 characters in length
148 // One problem we face is the image column type in reports which cannot accept nvarchar data
149 if (!empty($value) && !is_numeric(trim(str_replace(array('\'', ','), '', $value))) && !preg_match('/^\'[\,]\'$/', $value)) {
150 $replace[$value] = 'N' . trim($value, 'N');
155 if (!empty($replace))
156 $sql = str_replace(array_keys($replace), $replace, $sql);
159 $sql = str_replace(array_keys($pairs), $pairs, $sql);
161 if(strpos($sql, '<@#@#@PAIR@#@#@>'))
162 $sql = str_replace(array('<@#@#@PAIR@#@#@>'), array('\'\''), $sql);
164 if(strpos($sql, '<@#@#@ESCAPED_QUOTE@#@#@>'))
165 $sql = str_replace(array('<@#@#@ESCAPED_QUOTE@#@#@>'), array('\\\''), $sql);