1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
<?php
/**
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/
namespace Wikimedia\Rdbms;
use Wikimedia\Rdbms\Platform\SQLPlatform;
/**
* Holds information on Query to be executed
*
* @ingroup Database
* @internal
* @since 1.41
*/
class Query {
/**
* The possible multi-word values for getVerb().
* @internal For use by Query and QueryBuilderFromRawSQL only.
*/
public const MULTIWORD_VERBS = [
'RELEASE SAVEPOINT',
'ROLLBACK TO SAVEPOINT',
'CREATE TEMPORARY',
'CREATE INDEX',
'DROP INDEX',
'CREATE DATABASE',
'ALTER DATABASE',
'DROP DATABASE',
];
private string $sql;
private int $flags;
private string $queryVerb;
private ?string $writeTable;
private string $cleanedSql;
/**
* @param string $sql SQL statement text
* @param int $flags Bit field of ISQLPlatform::QUERY_CHANGE_* constants
* @param string $queryVerb The first words of the SQL statement that convey what kind of
* database/table/column/index command was specified. Except for the cases listed in
* {@see MULTIWORD_VERBS}, this will be the first word of the SQL statement.
* @param string|null $writeTable The table targeted for writes, if any. Can be omitted if
* it would be hard to identify the table (e.g. when parsing an arbitrary SQL string).
* @param string $cleanedSql Sanitized/simplified SQL statement text for logging.
* Typically, this means replacing variables / parameter values with placeholders.
* Can be omitted, in which case the code using the Query is responsible for sanitizing.
*/
public function __construct(
string $sql,
$flags,
$queryVerb,
?string $writeTable = null,
$cleanedSql = ''
) {
$this->sql = $sql;
$this->flags = $flags;
$this->queryVerb = $queryVerb;
$this->writeTable = $writeTable;
$this->cleanedSql = substr( $cleanedSql, 0, 255 );
}
public function isWriteQuery(): bool {
// Check if a SQL wrapper method already flagged the query as a non-write
if (
$this->fieldHasBit( $this->flags, SQLPlatform::QUERY_CHANGE_NONE ) ||
$this->fieldHasBit( $this->flags, SQLPlatform::QUERY_CHANGE_TRX ) ||
$this->fieldHasBit( $this->flags, SQLPlatform::QUERY_CHANGE_LOCKS )
) {
return false;
}
// Check if a SQL wrapper method already flagged the query as a write
if (
$this->fieldHasBit( $this->flags, SQLPlatform::QUERY_CHANGE_ROWS ) ||
$this->fieldHasBit( $this->flags, SQLPlatform::QUERY_CHANGE_SCHEMA ) ||
$this->fieldHasBit( $this->flags, SQLPlatform::QUERY_PSEUDO_PERMANENT )
) {
return true;
}
throw new DBLanguageError( __METHOD__ . ' called with incorrect flags parameter' );
}
public function getVerb(): string {
return $this->queryVerb;
}
private function fieldHasBit( int $flags, int $bit ): bool {
return ( ( $flags & $bit ) === $bit );
}
public function getSQL(): string {
return $this->sql;
}
public function getFlags(): int {
// The whole concept of flags is terrible. This should be deprecated.
return $this->flags;
}
/**
* Get the table which is being written to, or null for a read query or if
* the destination is unknown.
*/
public function getWriteTable(): ?string {
return $this->writeTable;
}
/**
* Get the cleaned/sanitized SQL statement text for logging.
* Might return an empty string, which means sanitization is the caller's responsibility.
*/
public function getCleanedSql(): string {
return $this->cleanedSql;
}
}
|