1<?php 2/** 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 * http://www.gnu.org/copyleft/gpl.html 17 * 18 * @file 19 */ 20 21namespace Wikimedia\Rdbms; 22 23/** 24 * Lazy-loaded wrapper for simplification and scrubbing of SQL queries for profiling 25 * 26 * @since 1.34 27 * @ingroup Profiler 28 * @ingroup Database 29 */ 30class GeneralizedSql { 31 /** @var string */ 32 private $rawSql; 33 /** @var string */ 34 private $trxId; 35 /** @var string */ 36 private $prefix; 37 38 /** @var string|null */ 39 private $genericSql; 40 41 /** 42 * @param string $rawSql 43 * @param string $trxId 44 * @param string $prefix 45 */ 46 public function __construct( $rawSql, $trxId, $prefix ) { 47 $this->rawSql = $rawSql; 48 $this->trxId = $trxId; 49 $this->prefix = $prefix; 50 } 51 52 /** 53 * Removes most variables from an SQL query and replaces them with X or N for numbers. 54 * It's only slightly flawed. Don't use for anything important. 55 * 56 * @param string $sql A SQL Query 57 * 58 * @return string 59 */ 60 private static function generalizeSQL( $sql ) { 61 # This does the same as the regexp below would do, but in such a way 62 # as to avoid crashing php on some large strings. 63 # $sql = preg_replace( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql ); 64 65 $sql = str_replace( "\\\\", '', $sql ); 66 $sql = str_replace( "\\'", '', $sql ); 67 $sql = str_replace( "\\\"", '', $sql ); 68 $sql = preg_replace( "/'.*'/s", "'X'", $sql ); 69 $sql = preg_replace( '/".*"/s', "'X'", $sql ); 70 71 # All newlines, tabs, etc replaced by single space 72 $sql = preg_replace( '/\s+/', ' ', $sql ); 73 74 # All numbers => N, 75 # except the ones surrounded by characters, e.g. l10n 76 $sql = preg_replace( '/-?\d+(,-?\d+)+/s', 'N,...,N', $sql ); 77 $sql = preg_replace( '/(?<![a-zA-Z])-?\d+(?![a-zA-Z])/s', 'N', $sql ); 78 79 return $sql; 80 } 81 82 /** 83 * @return string 84 */ 85 public function stringify() { 86 if ( $this->genericSql !== null ) { 87 return $this->genericSql; 88 } 89 90 $this->genericSql = $this->prefix . 91 substr( self::generalizeSQL( $this->rawSql ), 0, 255 ) . 92 ( $this->trxId ? " [TRX#{$this->trxId}]" : "" ); 93 94 return $this->genericSql; 95 } 96} 97