]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/database/FreeTDSManager.php
Release 6.2.0
[Github/sugarcrm.git] / include / database / FreeTDSManager.php
1 <?php
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.
6  * 
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.
13  * 
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
17  * details.
18  * 
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
22  * 02110-1301 USA.
23  * 
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.
26  * 
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.
30  * 
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  ********************************************************************************/
37
38
39 include_once('include/database/MssqlManager.php');
40
41 class FreeTDSManager extends MssqlManager
42 {
43
44         public $isFreeTDS = true;
45
46         /**
47      * @see DBManager::query()
48      */
49     public function query(
50         $sql,
51         $dieOnError = false,
52         $msg = '',
53         $suppress = false
54         )
55     {
56         $sql = $this->appendN($sql);
57         parent::countQuery($sql);
58         $GLOBALS['log']->info('Query:' . $sql);
59         $this->checkConnection();
60         $this->query_time = microtime(true);
61
62         if ($suppress) {
63         }
64         else {
65             $result = @mssql_query($sql,$this->database);
66         }
67
68         if (!$result) {
69
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');
75
76             if($dieOnError)
77                 if ($sqlpos !== false)
78                     // if sqlmsg has 'Changed database context to', just log it
79                     $GLOBALS['log']->debug(mssql_get_last_message() . ": " . $sql );
80                 else {
81                     $GLOBALS['log']->fatal('SQL Error : ' . mssql_get_last_message());
82                     sugar_die($GLOBALS['app_strings']['ERR_DB_FAIL']);
83                 }
84             else
85                 echo 'SQL Error : ' . mssql_get_last_message();
86
87             $GLOBALS['log']->fatal(mssql_get_last_message() . ": " . $sql );
88         }
89         $this->lastmysqlrow = -1;
90
91         $this->query_time = microtime(true) - $this->query_time;
92         $GLOBALS['log']->info('Query Execution Time:'.$this->query_time);
93
94
95         $this->checkError($msg.' Query Failed:' . $sql, $dieOnError);
96
97         return $result;
98     }
99
100
101     /**
102      * This is a utility function to prepend the "N" character in front of SQL values that are
103      * surrounded by single quotes.
104      *
105      * @param  $sql string SQL statement
106      * @return string SQL statement with single quote values prepended with "N" character for nvarchar columns
107      */
108     public function appendN(
109         $sql
110         )
111     {
112         // If there are no single quotes, don't bother, will just assume there is no character data
113         if (strpos($sql, '\'') === false)
114             return $sql;
115
116         $sql = str_replace('\\\'', '<@#@#@ESCAPED_QUOTE@#@#@>', $sql);
117
118         //The only location of three subsequent ' will be at the begning or end of a value.
119         $sql = preg_replace('/(?<!\')(\'{3})(?!\')/', "'<@#@#@PAIR@#@#@>", $sql);
120
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.');
124             return $sql;
125         }
126
127         // Remove any remaining '' and do not parse... replace later (hopefully we don't even have any)
128         $pairs        = array();
129         $regexp       = '/(\'{2})/';
130         $pair_matches = array();
131         preg_match_all($regexp, $sql, $pair_matches);
132         if ($pair_matches) {
133             foreach (array_unique($pair_matches[0]) as $key=>$value) {
134                $pairs['<@PAIR-'.$key.'@>'] = $value;
135             }
136             if (!empty($pairs)) {
137                $sql = str_replace($pairs, array_keys($pairs), $sql);
138             }
139         }
140
141         $regexp  = "/(N?\'.+?\')/is";
142         $matches = array();
143         preg_match_all($regexp, $sql, $matches);
144         $replace = array();
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');
151                 }
152             }
153         }
154
155         if (!empty($replace))
156             $sql = str_replace(array_keys($replace), $replace, $sql);
157
158         if (!empty($pairs))
159             $sql = str_replace(array_keys($pairs), $pairs, $sql);
160
161         if(strpos($sql, '<@#@#@PAIR@#@#@>'))
162             $sql = str_replace(array('<@#@#@PAIR@#@#@>'), array('\'\''), $sql);
163
164         if(strpos($sql, '<@#@#@ESCAPED_QUOTE@#@#@>'))
165             $sql = str_replace(array('<@#@#@ESCAPED_QUOTE@#@#@>'), array('\\\''), $sql);
166
167         return $sql;
168     }
169 }