PageRenderTime 40ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/include/database/FreeTDSManager.php

https://github.com/mikmagic/sugarcrm_dev
PHP | 169 lines | 93 code | 24 blank | 52 comment | 19 complexity | 72cca97832b03356146faa2d49a2cbed MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause, AGPL-3.0
  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. include_once('include/database/MssqlManager.php');
  38. class FreeTDSManager extends MssqlManager
  39. {
  40. public $isFreeTDS = true;
  41. /**
  42. * @see DBManager::query()
  43. */
  44. public function query(
  45. $sql,
  46. $dieOnError = false,
  47. $msg = '',
  48. $suppress = false
  49. )
  50. {
  51. $sql = $this->appendN($sql);
  52. parent::countQuery($sql);
  53. $GLOBALS['log']->info('Query:' . $sql);
  54. $this->checkConnection();
  55. $this->query_time = microtime(true);
  56. if ($suppress) {
  57. }
  58. else {
  59. $result = @mssql_query($sql,$this->database);
  60. }
  61. if (!$result) {
  62. // awu Bug 10657: ignoring mssql error message 'Changed database context to' - an intermittent
  63. // and difficult to reproduce error. The message is only a warning, and does
  64. // not affect the functionality of the query
  65. $sqlmsg = mssql_get_last_message();
  66. $sqlpos = strpos($sqlmsg, 'Changed database context to');
  67. if($dieOnError)
  68. if ($sqlpos !== false)
  69. // if sqlmsg has 'Changed database context to', just log it
  70. $GLOBALS['log']->debug(mssql_get_last_message() . ": " . $sql );
  71. else {
  72. $GLOBALS['log']->fatal('SQL Error : ' . mssql_get_last_message());
  73. sugar_die($GLOBALS['app_strings']['ERR_DB_FAIL']);
  74. }
  75. else
  76. echo 'SQL Error : ' . mssql_get_last_message();
  77. $GLOBALS['log']->fatal(mssql_get_last_message() . ": " . $sql );
  78. }
  79. $this->lastmysqlrow = -1;
  80. $this->query_time = microtime(true) - $this->query_time;
  81. $GLOBALS['log']->info('Query Execution Time:'.$this->query_time);
  82. $this->checkError($msg.' Query Failed:' . $sql, $dieOnError);
  83. return $result;
  84. }
  85. /**
  86. * This is a utility function to prepend the "N" character in front of SQL values that are
  87. * surrounded by single quotes.
  88. *
  89. * @param $sql string SQL statement
  90. * @return string SQL statement with single quote values prepended with "N" character for nvarchar columns
  91. */
  92. public function appendN(
  93. $sql
  94. )
  95. {
  96. // If there are no single quotes, don't bother, will just assume there is no character data
  97. if (strpos($sql, '\'') === false)
  98. return $sql;
  99. $sql = str_replace('\\\'', '<@#@#@ESCAPED_QUOTE@#@#@>', $sql);
  100. //The only location of three subsequent ' will be at the begning or end of a value.
  101. $sql = preg_replace('/(?<!\')(\'{3})(?!\')/', "'<@#@#@PAIR@#@#@>", $sql);
  102. // Flag if there are odd number of single quotes, just continue w/o trying to append N
  103. if ((substr_count($sql, '\'') & 1)) {
  104. $GLOBALS['log']->error('SQL statement[' . $sql . '] has odd number of single quotes.');
  105. return $sql;
  106. }
  107. // Remove any remaining '' and do not parse... replace later (hopefully we don't even have any)
  108. $pairs = array();
  109. $regexp = '/(\'{2})/';
  110. $pair_matches = array();
  111. preg_match_all($regexp, $sql, $pair_matches);
  112. if ($pair_matches) {
  113. foreach (array_unique($pair_matches[0]) as $key=>$value) {
  114. $pairs['<@PAIR-'.$key.'@>'] = $value;
  115. }
  116. if (!empty($pairs)) {
  117. $sql = str_replace($pairs, array_keys($pairs), $sql);
  118. }
  119. }
  120. $regexp = "/(N?\'.+?\')/is";
  121. $matches = array();
  122. preg_match_all($regexp, $sql, $matches);
  123. $replace = array();
  124. if (!empty($matches)) {
  125. foreach ($matches[0] as $key=>$value) {
  126. // We are assuming that all nvarchar columns are no more than 200 characters in length
  127. // One problem we face is the image column type in reports which cannot accept nvarchar data
  128. if (!empty($value) && !is_numeric(trim(str_replace(array('\'', ','), '', $value))) && !preg_match('/^\'[\,]\'$/', $value)) {
  129. $replace[$value] = 'N' . trim($value, 'N');
  130. }
  131. }
  132. }
  133. if (!empty($replace))
  134. $sql = str_replace(array_keys($replace), $replace, $sql);
  135. if (!empty($pairs))
  136. $sql = str_replace(array_keys($pairs), $pairs, $sql);
  137. if(strpos($sql, '<@#@#@PAIR@#@#@>'))
  138. $sql = str_replace(array('<@#@#@PAIR@#@#@>'), array('\'\''), $sql);
  139. if(strpos($sql, '<@#@#@ESCAPED_QUOTE@#@#@>'))
  140. $sql = str_replace(array('<@#@#@ESCAPED_QUOTE@#@#@>'), array('\\\''), $sql);
  141. return $sql;
  142. }
  143. }