Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | n/a |
0 / 0 |
n/a |
0 / 0 |
CRAP | n/a |
0 / 0 |
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 | namespace Wikimedia\Rdbms; |
21 | |
22 | use Exception; |
23 | use Wikimedia\ScopedCallback; |
24 | |
25 | /** |
26 | * @defgroup Database Database |
27 | * This group deals with database interface functions |
28 | * and query specifics/optimisations. |
29 | */ |
30 | |
31 | // Very long type annotations :( |
32 | // phpcs:disable Generic.Files.LineLength |
33 | |
34 | /** |
35 | * Interface to a relational database |
36 | * |
37 | * This is used for both primary databases and replicas, and used for both concrete |
38 | * connections, as well as wrappers around shared connections, like DBConnRef. |
39 | * |
40 | * As such, callers should not assume that the object represents a live connection |
41 | * (when using DBConnRef, the object may lazily defer the connection to the first query), |
42 | * and should not assume that they have complete control over the connection |
43 | * (when using DBConnRef, multiple objects may automatically share and reuse the same |
44 | * underlying connection). |
45 | * |
46 | * @ingroup Database |
47 | */ |
48 | interface IDatabase extends IReadableDatabase { |
49 | /** Callback triggered immediately due to no active transaction */ |
50 | public const TRIGGER_IDLE = 1; |
51 | /** Callback triggered by COMMIT */ |
52 | public const TRIGGER_COMMIT = 2; |
53 | /** Callback triggered by ROLLBACK */ |
54 | public const TRIGGER_ROLLBACK = 3; |
55 | /** Callback triggered by atomic section cancel (ROLLBACK TO SAVEPOINT) */ |
56 | public const TRIGGER_CANCEL = 4; |
57 | |
58 | /** Transaction is requested by regular caller outside of the DB layer */ |
59 | public const TRANSACTION_EXPLICIT = ''; |
60 | /** Transaction is requested internally via DBO_TRX/startAtomic() */ |
61 | public const TRANSACTION_INTERNAL = 'implicit'; |
62 | |
63 | /** Atomic section is not cancelable */ |
64 | public const ATOMIC_NOT_CANCELABLE = ''; |
65 | /** Atomic section is cancelable */ |
66 | public const ATOMIC_CANCELABLE = 'cancelable'; |
67 | |
68 | /** Commit/rollback is from outside the IDatabase handle and connection manager */ |
69 | public const FLUSHING_ONE = ''; |
70 | /** |
71 | * Commit/rollback is from the owning connection manager for the IDatabase handle |
72 | * @internal Only for use within the rdbms library |
73 | */ |
74 | public const FLUSHING_ALL_PEERS = 'flush'; |
75 | /** |
76 | * Commit/rollback is from the IDatabase handle internally |
77 | * @internal Only for use within the rdbms library |
78 | */ |
79 | public const FLUSHING_INTERNAL = 'flush-internal'; |
80 | |
81 | /** Estimate total time (RTT, scanning, waiting on locks, applying) */ |
82 | public const ESTIMATE_TOTAL = 'total'; |
83 | /** Estimate time to apply (scanning, applying) */ |
84 | public const ESTIMATE_DB_APPLY = 'apply'; |
85 | |
86 | /** Flag to return the lock acquisition timestamp (null if not acquired) */ |
87 | public const LOCK_TIMESTAMP = 1; |
88 | |
89 | /** Field for getLBInfo()/setLBInfo() */ |
90 | public const LB_TRX_ROUND_ID = 'trxRoundId'; |
91 | /** Field for getLBInfo()/setLBInfo() */ |
92 | public const LB_READ_ONLY_REASON = 'readOnlyReason'; |
93 | |
94 | /** Primary server than can stream writes to replica servers */ |
95 | public const ROLE_STREAMING_MASTER = 'streaming-master'; |
96 | /** Replica server that receives writes from a primary server */ |
97 | public const ROLE_STREAMING_REPLICA = 'streaming-replica'; |
98 | /** Replica server within a static dataset */ |
99 | public const ROLE_STATIC_CLONE = 'static-clone'; |
100 | /** Server with unknown topology role */ |
101 | public const ROLE_UNKNOWN = 'unknown'; |
102 | |
103 | /** |
104 | * Gets the current transaction level. |
105 | * |
106 | * Historically, transactions were allowed to be "nested". This is no |
107 | * longer supported, so this function really only returns a boolean. |
108 | * |
109 | * @return int The previous value |
110 | */ |
111 | public function trxLevel(); |
112 | |
113 | /** |
114 | * Get the UNIX timestamp of the time that the transaction was established |
115 | * |
116 | * This can be used to reason about the staleness of SELECT data in REPEATABLE-READ |
117 | * transaction isolation level. Callers can assume that if a view-snapshot isolation |
118 | * is used, then the data read by SQL queries is *at least* up to date to that point |
119 | * (possibly more up-to-date since the first SELECT defines the snapshot). |
120 | * |
121 | * @return float|null Returns null if there is not active transaction |
122 | * @since 1.25 |
123 | */ |
124 | public function trxTimestamp(); |
125 | |
126 | /** |
127 | * Check whether there is a transaction open at the specific request of a caller |
128 | * |
129 | * Explicit transactions are spawned by begin(), startAtomic(), and doAtomicSection(). |
130 | * Note that explicit transactions should not be confused with explicit transaction rounds. |
131 | * |
132 | * @return bool |
133 | * @since 1.28 |
134 | */ |
135 | public function explicitTrxActive(); |
136 | |
137 | /** |
138 | * Get properties passed down from the server info array of the load balancer |
139 | * |
140 | * @internal should not be called outside of rdbms library. |
141 | * |
142 | * @param string|null $name The entry of the info array to get, or null to get the whole array |
143 | * @return array|mixed|null |
144 | */ |
145 | public function getLBInfo( $name = null ); |
146 | |
147 | /** |
148 | * Get the sequence-based ID assigned by the last query method call |
149 | * |
150 | * This method should only be called when all the following hold true: |
151 | * - (a) A method call was made to insert(), upsert(), replace(), or insertSelect() |
152 | * - (b) The method call attempts to insert exactly one row |
153 | * - (c) The method call omits the value of exactly one auto-increment column |
154 | * - (d) The method call succeeded |
155 | * - (e) No subsequent method calls were made, with the exception of affectedRows(), |
156 | * lastErrno(), lastError(), and getType() |
157 | * |
158 | * In all other cases, the return value is unspecified. |
159 | * |
160 | * When the query method is either insert() with "IGNORE", upsert(), or insertSelect(), |
161 | * callers should first check affectedRows() before calling this method, making sure that |
162 | * the query method actually created a row. Otherwise, an ID from a previous insert might |
163 | * be incorrectly assumed to belong to last insert. |
164 | * |
165 | * @return int |
166 | */ |
167 | public function insertId(); |
168 | |
169 | /** |
170 | * Get the number of rows affected by the last query method call |
171 | * |
172 | * This method should only be called when all the following hold true: |
173 | * - (a) A method call was made to insert(), upsert(), replace(), update(), delete(), |
174 | * insertSelect(), query() with a non-SELECT statement, or queryMulti() with a |
175 | * non-SELECT terminal statement |
176 | * - (b) The method call succeeded |
177 | * - (c) No subsequent method calls were made, with the exception of affectedRows(), |
178 | * lastErrno(), lastError(), and getType() |
179 | * |
180 | * In all other cases, the return value is unspecified. |
181 | * |
182 | * UPDATE queries consider rows affected even when all their new column values match |
183 | * the previous values. Such rows can be excluded from the count by changing the WHERE |
184 | * clause to filter them out. |
185 | * |
186 | * If the last query method call was to query() or queryMulti(), then the results |
187 | * are based on the (last) statement provided to that call and are driver-specific. |
188 | * |
189 | * @return int |
190 | */ |
191 | public function affectedRows(); |
192 | |
193 | /** |
194 | * Run an SQL query statement and return the result |
195 | * |
196 | * If a connection loss is detected, then an attempt to reconnect will be made. |
197 | * For queries that involve no larger transactions or locks, they will be re-issued |
198 | * for convenience, provided the connection was re-established. |
199 | * |
200 | * In new code, the query wrappers select(), insert(), update(), delete(), |
201 | * etc. should be used where possible, since they give much better DBMS |
202 | * independence and automatically quote or validate user input in a variety |
203 | * of contexts. This function is generally only useful for queries which are |
204 | * explicitly DBMS-dependent and are unsupported by the query wrappers, such |
205 | * as CREATE TABLE. |
206 | * |
207 | * However, the query wrappers themselves should call this function. |
208 | * |
209 | * Callers should avoid the use of statements like BEGIN, COMMIT, and ROLLBACK. |
210 | * Methods like startAtomic(), endAtomic(), and cancelAtomic() can be used instead. |
211 | * |
212 | * @param string|Query $sql Single-statement SQL query |
213 | * @param-taint $sql exec_sql |
214 | * @param string $fname Caller name; used for profiling/SHOW PROCESSLIST comments @phan-mandatory-param |
215 | * @param int $flags Bit field of ISQLPlatform::QUERY_* constants |
216 | * @return bool|IResultWrapper True for a successful write query, IResultWrapper object |
217 | * for a successful read query, or false on failure if QUERY_SILENCE_ERRORS is set |
218 | * @return-taint tainted |
219 | * @throws DBQueryError If the query is issued, fails, and QUERY_SILENCE_ERRORS is not set |
220 | * @throws DBExpectedError If the query is not, and cannot, be issued yet (non-DBQueryError) |
221 | * @throws DBError If the query is inherently not allowed (non-DBExpectedError) |
222 | */ |
223 | public function query( $sql, $fname = __METHOD__, $flags = 0 ); |
224 | |
225 | /** |
226 | * Get an UpdateQueryBuilder bound to this connection. This is overridden by |
227 | * DBConnRef. |
228 | * |
229 | * @note A new query builder must be created per query. Query builders |
230 | * should not be reused since this uses a fluent interface and the state of |
231 | * the builder changes during the query which may cause unexpected results. |
232 | * |
233 | * @return UpdateQueryBuilder |
234 | */ |
235 | public function newUpdateQueryBuilder(): UpdateQueryBuilder; |
236 | |
237 | /** |
238 | * Get an DeleteQueryBuilder bound to this connection. This is overridden by |
239 | * DBConnRef. |
240 | * |
241 | * @note A new query builder must be created per query. Query builders |
242 | * should not be reused since this uses a fluent interface and the state of |
243 | * the builder changes during the query which may cause unexpected results. |
244 | * |
245 | * @return DeleteQueryBuilder |
246 | */ |
247 | public function newDeleteQueryBuilder(): DeleteQueryBuilder; |
248 | |
249 | /** |
250 | * Get an InsertQueryBuilder bound to this connection. This is overridden by |
251 | * DBConnRef. |
252 | * |
253 | * @note A new query builder must be created per query. Query builders |
254 | * should not be reused since this uses a fluent interface and the state of |
255 | * the builder changes during the query which may cause unexpected results. |
256 | * |
257 | * @return InsertQueryBuilder |
258 | */ |
259 | public function newInsertQueryBuilder(): InsertQueryBuilder; |
260 | |
261 | /** |
262 | * Get an ReplaceQueryBuilder bound to this connection. This is overridden by |
263 | * DBConnRef. |
264 | * |
265 | * @note A new query builder must be created per query. Query builders |
266 | * should not be reused since this uses a fluent interface and the state of |
267 | * the builder changes during the query which may cause unexpected results. |
268 | * |
269 | * @return ReplaceQueryBuilder |
270 | */ |
271 | public function newReplaceQueryBuilder(): ReplaceQueryBuilder; |
272 | |
273 | /** |
274 | * Lock all rows meeting the given conditions/options FOR UPDATE |
275 | * |
276 | * @param string|string[] $table The unqualified name of table(s) (use an array for a join) |
277 | * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds |
278 | * Condition in the format of IDatabase::select() conditions |
279 | * @param string $fname Function name for profiling @phan-mandatory-param |
280 | * @param array $options Options for select ("FOR UPDATE" is added automatically) |
281 | * @param array $join_conds Join conditions |
282 | * @return int Number of matching rows found (and locked) |
283 | * @throws DBError If an error occurs, {@see query} |
284 | * @since 1.32 |
285 | * @deprecated since 1.43; Use SelectQueryBuilder::acquireRowLocks |
286 | */ |
287 | public function lockForUpdate( |
288 | $table, $conds = '', $fname = __METHOD__, $options = [], $join_conds = [] |
289 | ); |
290 | |
291 | /** |
292 | * Insert row(s) into a table, in the provided order |
293 | * |
294 | * This operation will be seen by affectedRows()/insertId() as one query statement, |
295 | * regardless of how many statements are actually sent by the class implementation. |
296 | * |
297 | * @internal callers outside of rdbms library should use InsertQueryBuilder instead. |
298 | * |
299 | * @param string $table The unqualified name of a table |
300 | * @param array|array[] $rows Row(s) to insert, as either: |
301 | * - A string-keyed map of (column name => value) defining a new row. Values are |
302 | * treated as literals and quoted appropriately; null is interpreted as NULL. |
303 | * - An integer-keyed list of such string-keyed maps, defining a list of new rows. |
304 | * The keys in each map must be identical to each other and in the same order. |
305 | * The rows must not collide with each other. |
306 | * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param |
307 | * @param string|array $options Combination map/list where each string-keyed entry maps |
308 | * a non-boolean option to the option parameters and each integer-keyed value is the |
309 | * name of a boolean option. Supported options are: |
310 | * - IGNORE: Boolean: skip insertion of rows that would cause unique key conflicts. |
311 | * IDatabase::affectedRows() can be used to determine how many rows were inserted. |
312 | * @return bool Return true if no exception was thrown (deprecated since 1.33) |
313 | * @throws DBError If an error occurs, {@see query} |
314 | */ |
315 | public function insert( $table, $rows, $fname = __METHOD__, $options = [] ); |
316 | |
317 | /** |
318 | * Update all rows in a table that match a given condition |
319 | * |
320 | * This operation will be seen by affectedRows()/insertId() as one query statement, |
321 | * regardless of how many statements are actually sent by the class implementation. |
322 | * |
323 | * @internal callers outside of rdbms library should use UpdateQueryBuilder instead. |
324 | * |
325 | * @param string $table The unqualified name of a table |
326 | * @param-taint $table exec_sql |
327 | * @param array<string,?scalar|RawSQLValue>|array<int,string> $set |
328 | * Combination map/list where each string-keyed entry maps a column |
329 | * to a literal assigned value and each integer-keyed value is a SQL expression in the |
330 | * format of a column assignment within UPDATE...SET. The (column => value) entries are |
331 | * convenient due to automatic value quoting and conversion of null to NULL. The SQL |
332 | * assignment format is useful for updates like "column = column + X". All assignments |
333 | * have no defined execution order, so they should not depend on each other. Do not |
334 | * modify AUTOINCREMENT or UUID columns in assignments. |
335 | * @param-taint $set exec_sql_numkey |
336 | * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds |
337 | * Condition in the format of IDatabase::select() conditions. |
338 | * In order to prevent possible performance or replication issues or damaging a data |
339 | * accidentally, an empty condition for 'update' queries isn't allowed. |
340 | * IDatabase::ALL_ROWS should be passed explicitly in order to update all rows. |
341 | * @param-taint $conds exec_sql_numkey |
342 | * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param |
343 | * @param-taint $fname exec_sql |
344 | * @param string|array $options Combination map/list where each string-keyed entry maps |
345 | * a non-boolean option to the option parameters and each integer-keyed value is the |
346 | * name of a boolean option. Supported options are: |
347 | * - IGNORE: Boolean: skip update of rows that would cause unique key conflicts. |
348 | * IDatabase::affectedRows() includes all matching rows, |
349 | * that includes also rows not updated due to key conflict. |
350 | * @param-taint $options none |
351 | * @return bool Return true if no exception was thrown (deprecated since 1.33) |
352 | * @return-taint none |
353 | * @throws DBError If an error occurs, {@see query} |
354 | */ |
355 | public function update( $table, $set, $conds, $fname = __METHOD__, $options = [] ); |
356 | |
357 | /** |
358 | * Insert row(s) into a table, in the provided order, while deleting conflicting rows |
359 | * |
360 | * Conflicts are determined by the provided unique indexes. Note that it is possible |
361 | * for the provided rows to conflict even among themselves; it is preferable for the |
362 | * caller to de-duplicate such input beforehand. |
363 | * |
364 | * Note some important implications of the deletion semantics: |
365 | * - If the table has an AUTOINCREMENT column and $rows omit that column, then any |
366 | * conflicting existing rows will be replaced with newer having higher values for |
367 | * that column, even if nothing else changed. |
368 | * - There might be worse contention than upsert() due to the use of gap-locking. |
369 | * This does not apply to RDBMS types that use predicate locking nor those that |
370 | * just lock the whole table or databases anyway. |
371 | * |
372 | * This operation will be seen by affectedRows()/insertId() as one query statement, |
373 | * regardless of how many statements are actually sent by the class implementation. |
374 | * |
375 | * @internal callers outside of rdbms library should use ReplaceQueryBuilder instead. |
376 | * |
377 | * @param string $table The unqualified name of a table |
378 | * @param string|string[]|string[][] $uniqueKeys Column name or non-empty list of column |
379 | * name lists that define all applicable unique keys on the table. There must only be |
380 | * one such key. Each unique key on the table is "applicable" unless either: |
381 | * - It involves an AUTOINCREMENT column for which no values are assigned in $rows |
382 | * - It involves a UUID column for which newly generated UUIDs are assigned in $rows |
383 | * @param array|array[] $rows Row(s) to insert, in the form of either: |
384 | * - A string-keyed map of (column name => value) defining a new row. Values are |
385 | * treated as literals and quoted appropriately; null is interpreted as NULL. |
386 | * Columns belonging to a key in $uniqueKeys must be defined here and non-null. |
387 | * - An integer-keyed list of such string-keyed maps, defining a list of new rows. |
388 | * The keys in each map must be identical to each other and in the same order. |
389 | * The rows must not collide with each other. |
390 | * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param |
391 | * @throws DBError If an error occurs, {@see query} |
392 | */ |
393 | public function replace( $table, $uniqueKeys, $rows, $fname = __METHOD__ ); |
394 | |
395 | /** |
396 | * Upsert row(s) into a table, in the provided order, while updating conflicting rows |
397 | * |
398 | * Conflicts are determined by the provided unique indexes. Note that it is possible |
399 | * for the provided rows to conflict even among themselves; it is preferable for the |
400 | * caller to de-duplicate such input beforehand. |
401 | * |
402 | * This operation will be seen by affectedRows()/insertId() as one query statement, |
403 | * regardless of how many statements are actually sent by the class implementation. |
404 | * |
405 | * @internal callers outside of rdbms library should use InsertQueryBuilder instead. |
406 | * |
407 | * @param string $table The unqualified name of a table |
408 | * @param array|array[] $rows Row(s) to insert, in the form of either: |
409 | * - A string-keyed map of (column name => value) defining a new row. Values are |
410 | * treated as literals and quoted appropriately; null is interpreted as NULL. |
411 | * Columns belonging to a key in $uniqueKeys must be defined here and non-null. |
412 | * - An integer-keyed list of such string-keyed maps, defining a list of new rows. |
413 | * The keys in each map must be identical to each other and in the same order. |
414 | * The rows must not collide with each other. |
415 | * @param string|string[]|string[][] $uniqueKeys Column name or non-empty list of column |
416 | * name lists that define all applicable unique keys on the table. There must only be |
417 | * one such key. Each unique key on the table is "applicable" unless either: |
418 | * - It involves an AUTOINCREMENT column for which no values are assigned in $rows |
419 | * - It involves a UUID column for which newly generated UUIDs are assigned in $rows |
420 | * @param array<string,?scalar|RawSQLValue>|array<int,string> $set |
421 | * Combination map/list where each string-keyed entry maps a column |
422 | * to a literal assigned value and each integer-keyed value is a SQL assignment expression |
423 | * of the form "<unquoted alphanumeric column> = <SQL expression>". The (column => value) |
424 | * entries are convenient due to automatic value quoting and conversion of null to NULL. |
425 | * The SQL assignment entries are useful for updates like "column = column + X". All of |
426 | * the assignments have no defined execution order, so callers should make sure that they |
427 | * not depend on each other. Do not modify AUTOINCREMENT or UUID columns in assignments, |
428 | * even if they are just "secondary" unique keys. For multi-row upserts, use |
429 | * buildExcludedValue() to reference the value of a column from the corresponding row |
430 | * in $rows that conflicts with the current row. |
431 | * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param |
432 | * @throws DBError If an error occurs, {@see query} |
433 | * @since 1.22 |
434 | */ |
435 | public function upsert( |
436 | $table, array $rows, $uniqueKeys, array $set, $fname = __METHOD__ |
437 | ); |
438 | |
439 | /** |
440 | * Delete all rows in a table that match a condition which includes a join |
441 | * |
442 | * For safety, an empty $conds will not delete everything. If you want to |
443 | * delete all rows where the join condition matches, set $conds=IDatabase::ALL_ROWS. |
444 | * |
445 | * DO NOT put the join condition in $conds. |
446 | * |
447 | * This operation will be seen by affectedRows()/insertId() as one query statement, |
448 | * regardless of how many statements are actually sent by the class implementation. |
449 | * |
450 | * @param string $delTable The unqualified name of the table to delete rows from. |
451 | * @param string $joinTable The unqualified name of the reference table to join on. |
452 | * @param string $delVar The variable to join on, in the first table. |
453 | * @param string $joinVar The variable to join on, in the second table. |
454 | * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds |
455 | * Condition array of field names mapped to variables, |
456 | * ANDed together in the WHERE clause |
457 | * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param |
458 | * @throws DBError If an error occurs, {@see query} |
459 | */ |
460 | public function deleteJoin( |
461 | $delTable, |
462 | $joinTable, |
463 | $delVar, |
464 | $joinVar, |
465 | $conds, |
466 | $fname = __METHOD__ |
467 | ); |
468 | |
469 | /** |
470 | * Delete all rows in a table that match a condition |
471 | * |
472 | * This operation will be seen by affectedRows()/insertId() as one query statement, |
473 | * regardless of how many statements are actually sent by the class implementation. |
474 | * |
475 | * @internal callers outside of rdbms library should use DeleteQueryBuilder instead. |
476 | * |
477 | * @param string $table The unqualified name of a table |
478 | * @param-taint $table exec_sql |
479 | * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds |
480 | * Array of conditions. See $conds in IDatabase::select() |
481 | * In order to prevent possible performance or replication issues or damaging a data |
482 | * accidentally, an empty condition for 'delete' queries isn't allowed. |
483 | * IDatabase::ALL_ROWS should be passed explicitly in order to delete all rows. |
484 | * @param-taint $conds exec_sql_numkey |
485 | * @param string $fname Name of the calling function @phan-mandatory-param |
486 | * @param-taint $fname exec_sql |
487 | * @return bool Return true if no exception was thrown (deprecated since 1.33) |
488 | * @return-taint none |
489 | * @throws DBError If an error occurs, {@see query} |
490 | */ |
491 | public function delete( $table, $conds, $fname = __METHOD__ ); |
492 | |
493 | /** |
494 | * INSERT SELECT wrapper |
495 | * |
496 | * @warning If the insert will use an auto-increment or sequence to |
497 | * determine the value of a column, this may break replication on |
498 | * databases using statement-based replication if the SELECT is not |
499 | * deterministically ordered. |
500 | * |
501 | * This operation will be seen by affectedRows()/insertId() as one query statement, |
502 | * regardless of how many statements are actually sent by the class implementation. |
503 | * |
504 | * @param string $destTable Unqualified name of destination table |
505 | * @param string|array $srcTable Unqualified name of source table(s) (use an array for a join) |
506 | * @param array $varMap Must be an associative array of the form |
507 | * [ 'dest1' => 'source1', ... ]. Source items may be literals |
508 | * rather than field names, but strings should be quoted with |
509 | * IDatabase::addQuotes() |
510 | * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds |
511 | * Condition array. See $conds in IDatabase::select() for |
512 | * the details of the format of condition arrays. May be "*" to copy the |
513 | * whole table. |
514 | * @param string $fname The function name of the caller, from __METHOD__ @phan-mandatory-param |
515 | * @param array $insertOptions Options for the INSERT part of the query, see |
516 | * IDatabase::insert() for details. Also, one additional option is |
517 | * available: pass 'NO_AUTO_COLUMNS' to hint that the query does not use |
518 | * an auto-increment or sequence to determine any column values. |
519 | * @param array $selectOptions Options for the SELECT part of the query, see |
520 | * IDatabase::select() for details. |
521 | * @param array $selectJoinConds Join conditions for the SELECT part of the query, see |
522 | * IDatabase::select() for details. |
523 | * @return bool Return true if no exception was thrown (deprecated since 1.33) |
524 | * @throws DBError If an error occurs, {@see query} |
525 | */ |
526 | public function insertSelect( |
527 | $destTable, |
528 | $srcTable, |
529 | $varMap, |
530 | $conds, |
531 | $fname = __METHOD__, |
532 | $insertOptions = [], |
533 | $selectOptions = [], |
534 | $selectJoinConds = [] |
535 | ); |
536 | |
537 | /** |
538 | * Run a callback when the current transaction commits or rolls back |
539 | * |
540 | * An error is thrown if no transaction is pending. |
541 | * |
542 | * When transaction round mode (DBO_TRX) is set, the callback will run at the end |
543 | * of the round, just after all peer transactions COMMIT/ROLLBACK. |
544 | * |
545 | * This IDatabase instance will start off in auto-commit mode when the callback starts. |
546 | * The use of other IDatabase handles from the callback should be avoided unless they are |
547 | * known to be in auto-commit mode. Callbacks that create transactions via begin() or |
548 | * startAtomic() must have matching calls to commit()/endAtomic(). |
549 | * |
550 | * Use this method only for the following purposes: |
551 | * - (a) Release of cooperative locks on resources |
552 | * - (b) Cancellation of in-process deferred tasks |
553 | * |
554 | * The callback takes the following arguments: |
555 | * - How the current atomic section (if any) or overall transaction (otherwise) ended |
556 | * (IDatabase::TRIGGER_COMMIT or IDatabase::TRIGGER_ROLLBACK) |
557 | * - This IDatabase instance (since 1.32) |
558 | * |
559 | * Callbacks will execute in the order they were enqueued. |
560 | * |
561 | * @param callable $callback |
562 | * @param string $fname Caller name @phan-mandatory-param |
563 | * @throws DBError If an error occurs, {@see query} |
564 | * @throws Exception If the callback runs immediately and an error occurs in it |
565 | * @since 1.28 |
566 | */ |
567 | public function onTransactionResolution( callable $callback, $fname = __METHOD__ ); |
568 | |
569 | /** |
570 | * Run a callback when the current transaction commits or now if there is none |
571 | * |
572 | * If there is a transaction and it is rolled back, then the callback is cancelled. |
573 | * |
574 | * When transaction round mode (DBO_TRX) is set, the callback will run at the end |
575 | * of the round, just after all peer transactions COMMIT. If the transaction round |
576 | * is rolled back, then the callback is cancelled. |
577 | * |
578 | * This IDatabase instance will start off in auto-commit mode when the callback starts. |
579 | * The use of other IDatabase handles from the callback should be avoided unless they are |
580 | * known to be in auto-commit mode. Callbacks that create transactions via begin() or |
581 | * startAtomic() must have matching calls to commit()/endAtomic(). |
582 | * |
583 | * Use this method only for the following purposes: |
584 | * - (a) RDBMS updates, prone to lock timeouts/deadlocks, that do not require |
585 | * atomicity with respect to the updates in the current transaction (if any) |
586 | * - (b) Purges to lightweight cache services due to RDBMS updates |
587 | * - (c) Updates to secondary DBs/stores that must only commit once the updates in |
588 | * the current transaction (if any) are committed (e.g. insert user account row |
589 | * to DB1, then, initialize corresponding LDAP account) |
590 | * |
591 | * The callback takes the following arguments: |
592 | * - How the transaction ended (IDatabase::TRIGGER_COMMIT or IDatabase::TRIGGER_IDLE) |
593 | * - This IDatabase instance (since 1.32) |
594 | * |
595 | * Callbacks will execute in the order they were enqueued. |
596 | * |
597 | * @param callable $callback |
598 | * @param string $fname Caller name @phan-mandatory-param |
599 | * @throws DBError If an error occurs, {@see query} |
600 | * @throws Exception If the callback runs immediately and an error occurs in it |
601 | * @since 1.32 |
602 | */ |
603 | public function onTransactionCommitOrIdle( callable $callback, $fname = __METHOD__ ); |
604 | |
605 | /** |
606 | * Run a callback before the current transaction commits or now if there is none |
607 | * |
608 | * If there is a transaction and it is rolled back, then the callback is cancelled. |
609 | * |
610 | * When transaction round mode (DBO_TRX) is set, the callback will run at the end |
611 | * of the round, just after all peer transactions COMMIT. If the transaction round |
612 | * is rolled back, then the callback is cancelled. |
613 | * |
614 | * If there is no current transaction, one will be created to wrap the callback. |
615 | * Callbacks cannot use begin()/commit() to manage transactions. The use of other |
616 | * IDatabase handles from the callback should be avoided. |
617 | * |
618 | * Use this method only for the following purposes: |
619 | * - a) RDBMS updates, prone to lock timeouts/deadlocks, that require atomicity |
620 | * with respect to the updates in the current transaction (if any) |
621 | * - b) Purges to lightweight cache services due to RDBMS updates |
622 | * |
623 | * The callback takes the one argument: |
624 | * - This IDatabase instance (since 1.32) |
625 | * |
626 | * Callbacks will execute in the order they were enqueued. |
627 | * |
628 | * @param callable $callback |
629 | * @param string $fname Caller name @phan-mandatory-param |
630 | * @throws DBError If an error occurs, {@see query} |
631 | * @throws Exception If the callback runs immediately and an error occurs in it |
632 | * @since 1.22 |
633 | */ |
634 | public function onTransactionPreCommitOrIdle( callable $callback, $fname = __METHOD__ ); |
635 | |
636 | /** |
637 | * Begin an atomic section of SQL statements |
638 | * |
639 | * Start an implicit transaction if no transaction is already active, set a savepoint |
640 | * (if $cancelable is ATOMIC_CANCELABLE), and track the given section name to enforce |
641 | * that the transaction is not committed prematurely. The end of the section must be |
642 | * signified exactly once, either by endAtomic() or cancelAtomic(). Sections can have |
643 | * have layers of inner sections (sub-sections), but all sections must be ended in order |
644 | * of innermost to outermost. Transactions cannot be started or committed until all |
645 | * atomic sections are closed. |
646 | * |
647 | * ATOMIC_CANCELABLE is useful when the caller needs to handle specific failure cases |
648 | * by discarding the section's writes. This should not be used for failures when: |
649 | * - upsert() could easily be used instead |
650 | * - insert() with IGNORE could easily be used instead |
651 | * - select() with FOR UPDATE could be checked before issuing writes instead |
652 | * - The failure is from code that runs after the first write but doesn't need to |
653 | * - The failures are from contention solvable via onTransactionPreCommitOrIdle() |
654 | * - The failures are deadlocks; the RDBMs usually discard the whole transaction |
655 | * |
656 | * @note callers must use additional measures for situations involving two or more |
657 | * (peer) transactions (e.g. updating two database servers at once). The transaction |
658 | * and savepoint logic of this method only applies to this specific IDatabase instance. |
659 | * |
660 | * Example usage: |
661 | * @code |
662 | * // Start a transaction if there isn't one already |
663 | * $dbw->startAtomic( __METHOD__ ); |
664 | * // Serialize these thread table updates |
665 | * $dbw->select( 'thread', '1', [ 'td_id' => $tid ], __METHOD__, 'FOR UPDATE' ); |
666 | * // Add a new comment for the thread |
667 | * $dbw->insert( 'comment', $row, __METHOD__ ); |
668 | * $cid = $db->insertId(); |
669 | * // Update thread reference to last comment |
670 | * $dbw->update( 'thread', [ 'td_latest' => $cid ], [ 'td_id' => $tid ], __METHOD__ ); |
671 | * // Demark the end of this conceptual unit of updates |
672 | * $dbw->endAtomic( __METHOD__ ); |
673 | * @endcode |
674 | * |
675 | * Example usage (atomic changes that might have to be discarded): |
676 | * @code |
677 | * // Start a transaction if there isn't one already |
678 | * $sectionId = $dbw->startAtomic( __METHOD__, $dbw::ATOMIC_CANCELABLE ); |
679 | * // Create new record metadata row |
680 | * $dbw->insert( 'records', $row, __METHOD__ ); |
681 | * // Figure out where to store the data based on the new row's ID |
682 | * $path = $recordDirectory . '/' . $dbw->insertId(); |
683 | * // Write the record data to the storage system |
684 | * $status = $fileBackend->create( [ 'dst' => $path, 'content' => $data ] ); |
685 | * if ( $status->isOK() ) { |
686 | * // Try to cleanup files orphaned by transaction rollback |
687 | * $dbw->onTransactionResolution( |
688 | * function ( $type ) use ( $fileBackend, $path ) { |
689 | * if ( $type === IDatabase::TRIGGER_ROLLBACK ) { |
690 | * $fileBackend->delete( [ 'src' => $path ] ); |
691 | * } |
692 | * }, |
693 | * __METHOD__ |
694 | * ); |
695 | * // Demark the end of this conceptual unit of updates |
696 | * $dbw->endAtomic( __METHOD__ ); |
697 | * } else { |
698 | * // Discard these writes from the transaction (preserving prior writes) |
699 | * $dbw->cancelAtomic( __METHOD__, $sectionId ); |
700 | * } |
701 | * @endcode |
702 | * |
703 | * @since 1.23 |
704 | * @param string $fname @phan-mandatory-param |
705 | * @param string $cancelable Pass self::ATOMIC_CANCELABLE to use a |
706 | * savepoint and enable self::cancelAtomic() for this section. |
707 | * @return AtomicSectionIdentifier section ID token |
708 | * @throws DBError If an error occurs, {@see query} |
709 | */ |
710 | public function startAtomic( $fname = __METHOD__, $cancelable = self::ATOMIC_NOT_CANCELABLE ); |
711 | |
712 | /** |
713 | * Ends an atomic section of SQL statements |
714 | * |
715 | * Ends the next section of atomic SQL statements and commits the transaction |
716 | * if necessary. |
717 | * |
718 | * @since 1.23 |
719 | * @see IDatabase::startAtomic |
720 | * @param string $fname @phan-mandatory-param |
721 | * @throws DBError If an error occurs, {@see query} |
722 | */ |
723 | public function endAtomic( $fname = __METHOD__ ); |
724 | |
725 | /** |
726 | * Cancel an atomic section of SQL statements |
727 | * |
728 | * This will roll back only the statements executed since the start of the |
729 | * most recent atomic section, and close that section. If a transaction was |
730 | * open before the corresponding startAtomic() call, any statements before |
731 | * that call are *not* rolled back and the transaction remains open. If the |
732 | * corresponding startAtomic() implicitly started a transaction, that |
733 | * transaction is rolled back. |
734 | * |
735 | * @note callers must use additional measures for situations involving two or more |
736 | * (peer) transactions (e.g. updating two database servers at once). The transaction |
737 | * and savepoint logic of startAtomic() are bound to specific IDatabase instances. |
738 | * |
739 | * Note that a call to IDatabase::rollback() will also roll back any open atomic sections. |
740 | * |
741 | * @note As an optimization to save rountrips, this method may only be called |
742 | * when startAtomic() was called with the ATOMIC_CANCELABLE flag. |
743 | * @since 1.31 |
744 | * @see IDatabase::startAtomic |
745 | * @param string $fname @phan-mandatory-param |
746 | * @param AtomicSectionIdentifier|null $sectionId Section ID from startAtomic(); |
747 | * passing this enables cancellation of unclosed nested sections [optional] |
748 | * @throws DBError If an error occurs, {@see query} |
749 | */ |
750 | public function cancelAtomic( $fname = __METHOD__, ?AtomicSectionIdentifier $sectionId = null ); |
751 | |
752 | /** |
753 | * Perform an atomic section of reversible SQL statements from a callback |
754 | * |
755 | * The $callback takes the following arguments: |
756 | * - This database object |
757 | * - The value of $fname |
758 | * |
759 | * This will execute the callback inside a pair of startAtomic()/endAtomic() calls. |
760 | * If any exception occurs during execution of the callback, it will be handled as follows: |
761 | * - If $cancelable is ATOMIC_CANCELABLE, cancelAtomic() will be called to back out any |
762 | * (and only) statements executed during the atomic section. If that succeeds, then the |
763 | * exception will be re-thrown; if it fails, then a different exception will be thrown |
764 | * and any further query attempts will fail until rollback() is called. |
765 | * - If $cancelable is ATOMIC_NOT_CANCELABLE, cancelAtomic() will be called to mark the |
766 | * end of the section and the error will be re-thrown. Any further query attempts will |
767 | * fail until rollback() is called. |
768 | * |
769 | * This method is convenient for letting calls to the caller of this method be wrapped |
770 | * in a try/catch blocks for exception types that imply that the caller failed but was |
771 | * able to properly discard the changes it made in the transaction. This method can be |
772 | * an alternative to explicit calls to startAtomic()/endAtomic()/cancelAtomic(). |
773 | * |
774 | * Example usage, "RecordStore::save" method: |
775 | * @code |
776 | * $dbw->doAtomicSection( __METHOD__, function ( $dbw ) use ( $record ) { |
777 | * // Create new record metadata row |
778 | * $dbw->insert( 'records', $record->toArray(), __METHOD__ ); |
779 | * // Figure out where to store the data based on the new row's ID |
780 | * $path = $this->recordDirectory . '/' . $dbw->insertId(); |
781 | * // Write the record data to the storage system; |
782 | * // blob store throws StoreFailureException on failure |
783 | * $this->blobStore->create( $path, $record->getJSON() ); |
784 | * // Try to cleanup files orphaned by transaction rollback |
785 | * $dbw->onTransactionResolution( |
786 | * function ( $type ) use ( $path ) { |
787 | * if ( $type === IDatabase::TRIGGER_ROLLBACK ) { |
788 | * $this->blobStore->delete( $path ); |
789 | * } |
790 | * }, |
791 | * __METHOD__ |
792 | * ); |
793 | * }, $dbw::ATOMIC_CANCELABLE ); |
794 | * @endcode |
795 | * |
796 | * Example usage, caller of the "RecordStore::save" method: |
797 | * @code |
798 | * $dbw->startAtomic( __METHOD__ ); |
799 | * // ...various SQL writes happen... |
800 | * try { |
801 | * $recordStore->save( $record ); |
802 | * } catch ( StoreFailureException $e ) { |
803 | * // ...various SQL writes happen... |
804 | * } |
805 | * // ...various SQL writes happen... |
806 | * $dbw->endAtomic( __METHOD__ ); |
807 | * @endcode |
808 | * |
809 | * @see Database::startAtomic |
810 | * @see Database::endAtomic |
811 | * @see Database::cancelAtomic |
812 | * |
813 | * @param string $fname Caller name (usually __METHOD__) @phan-mandatory-param |
814 | * @param callable $callback Callback that issues write queries |
815 | * @param string $cancelable Pass self::ATOMIC_CANCELABLE to use a |
816 | * savepoint and enable self::cancelAtomic() for this section. |
817 | * @return mixed Result of the callback (since 1.28) |
818 | * @throws DBError If an error occurs, {@see query} |
819 | * @throws Exception If an error occurs in the callback |
820 | * @since 1.27; prior to 1.31 this did a rollback() instead of |
821 | * cancelAtomic(), and assumed no callers up the stack would ever try to |
822 | * catch the exception. |
823 | */ |
824 | public function doAtomicSection( |
825 | $fname, callable $callback, $cancelable = self::ATOMIC_NOT_CANCELABLE |
826 | ); |
827 | |
828 | /** |
829 | * Begin a transaction |
830 | * |
831 | * Only call this from code with outer transaction scope. |
832 | * See https://www.mediawiki.org/wiki/Database_transactions for details. |
833 | * Nesting of transactions is not supported. |
834 | * |
835 | * Note that when the DBO_TRX flag is set (which is usually the case for web |
836 | * requests, but not for maintenance scripts), any previous database query |
837 | * will have started a transaction automatically. |
838 | * |
839 | * Nesting of transactions is not supported. Attempts to nest transactions |
840 | * will cause a warning, unless the current transaction was started |
841 | * automatically because of the DBO_TRX flag. |
842 | * |
843 | * @param string $fname Calling function name @phan-mandatory-param |
844 | * @param string $mode A situationally valid IDatabase::TRANSACTION_* constant [optional] |
845 | * @throws DBError If an error occurs, {@see query} |
846 | */ |
847 | public function begin( $fname = __METHOD__, $mode = self::TRANSACTION_EXPLICIT ); |
848 | |
849 | /** |
850 | * Commits a transaction previously started using begin() |
851 | * |
852 | * If no transaction is in progress, a warning is issued. |
853 | * |
854 | * Only call this from code with outer transaction scope. |
855 | * See https://www.mediawiki.org/wiki/Database_transactions for details. |
856 | * Nesting of transactions is not supported. |
857 | * |
858 | * @param string $fname @phan-mandatory-param |
859 | * @param string $flush Flush flag, set to situationally valid IDatabase::FLUSHING_* |
860 | * constant to disable warnings about explicitly committing implicit transactions, |
861 | * or calling commit when no transaction is in progress. |
862 | * This will trigger an exception if there is an ongoing explicit transaction. |
863 | * Only set the flush flag if you are sure that these warnings are not applicable, |
864 | * and no explicit transactions are open. |
865 | * @throws DBError If an error occurs, {@see query} |
866 | */ |
867 | public function commit( $fname = __METHOD__, $flush = self::FLUSHING_ONE ); |
868 | |
869 | /** |
870 | * Rollback a transaction previously started using begin() |
871 | * |
872 | * Only call this from code with outer transaction scope. |
873 | * See https://www.mediawiki.org/wiki/Database_transactions for details. |
874 | * Nesting of transactions is not supported. If a serious unexpected error occurs, |
875 | * throwing an Exception is preferable, using a pre-installed error handler to trigger |
876 | * rollback (in any case, failure to issue COMMIT will cause rollback server-side). |
877 | * |
878 | * Query, connection, and onTransaction* callback errors will be suppressed and logged. |
879 | * |
880 | * @param string $fname Calling function name @phan-mandatory-param |
881 | * @param string $flush Flush flag, set to a situationally valid IDatabase::FLUSHING_* |
882 | * constant to disable warnings about explicitly rolling back implicit transactions. |
883 | * This will silently break any ongoing explicit transaction. Only set the flush flag |
884 | * if you are sure that it is safe to ignore these warnings in your context. |
885 | * @throws DBError If an error occurs, {@see query} |
886 | * @since 1.23 Added $flush parameter |
887 | */ |
888 | public function rollback( $fname = __METHOD__, $flush = self::FLUSHING_ONE ); |
889 | |
890 | /** |
891 | * Commit any transaction but error out if writes or callbacks are pending |
892 | * |
893 | * This is intended for clearing out REPEATABLE-READ snapshots so that callers can |
894 | * see a new point-in-time of the database. This is useful when one of many transaction |
895 | * rounds finished and significant time will pass in the script's lifetime. It is also |
896 | * useful to call on a replica server after waiting on replication to catch up to the |
897 | * primary server. |
898 | * |
899 | * @param string $fname Calling function name @phan-mandatory-param |
900 | * @param string $flush Flush flag, set to situationally valid IDatabase::FLUSHING_* |
901 | * constant to disable warnings about explicitly committing implicit transactions, |
902 | * or calling commit when no transaction is in progress. |
903 | * This will trigger an exception if there is an ongoing explicit transaction. |
904 | * Only set the flush flag if you are sure that these warnings are not applicable, |
905 | * and no explicit transactions are open. |
906 | * @throws DBError If an error occurs, {@see query} |
907 | * @since 1.28 |
908 | * @since 1.34 Added $flush parameter |
909 | */ |
910 | public function flushSnapshot( $fname = __METHOD__, $flush = self::FLUSHING_ONE ); |
911 | |
912 | /** |
913 | * Override database's default behavior. |
914 | * Not all options are supported on all database backends; |
915 | * unsupported options are silently ignored. |
916 | * |
917 | * $options include: |
918 | * - 'connTimeout': Set the connection timeout value in seconds. |
919 | * May be useful for very long batch queries such as full-wiki dumps, |
920 | * where a single query reads out over hours or days. |
921 | * Only supported on MySQL and MariaDB. |
922 | * - 'groupConcatMaxLen': Maximum length of a GROUP_CONCAT() result. |
923 | * Only supported on MySQL and MariaDB. |
924 | * |
925 | * @param array $options |
926 | * @return void |
927 | * @throws DBError If an error occurs, {@see query} |
928 | */ |
929 | public function setSessionOptions( array $options ); |
930 | |
931 | /** |
932 | * Check to see if a named lock is not locked by any thread (non-blocking) |
933 | * |
934 | * @param string $lockName Name of lock to poll |
935 | * @param string $method Name of method calling us |
936 | * @return bool |
937 | * @throws DBError If an error occurs, {@see query} |
938 | * @since 1.20 |
939 | */ |
940 | public function lockIsFree( $lockName, $method ); |
941 | |
942 | /** |
943 | * Acquire a named lock |
944 | * |
945 | * Named locks are not related to transactions |
946 | * |
947 | * @param string $lockName Name of lock to acquire |
948 | * @param string $method Name of the calling method |
949 | * @param int $timeout Acquisition timeout in seconds (0 means non-blocking) |
950 | * @param int $flags Bit field of IDatabase::LOCK_* constants |
951 | * @return bool|float|null Success (bool); acquisition time (float/null) if LOCK_TIMESTAMP |
952 | * @throws DBError If an error occurs, {@see query} |
953 | */ |
954 | public function lock( $lockName, $method, $timeout = 5, $flags = 0 ); |
955 | |
956 | /** |
957 | * Release a lock |
958 | * |
959 | * Named locks are not related to transactions |
960 | * |
961 | * @param string $lockName Name of lock to release |
962 | * @param string $method Name of the calling method |
963 | * @return bool Success |
964 | * @throws DBError If an error occurs, {@see query} |
965 | */ |
966 | public function unlock( $lockName, $method ); |
967 | |
968 | /** |
969 | * Acquire a named lock, flush any transaction, and return an RAII style unlocker object |
970 | * |
971 | * Only call this from outer transaction scope and when only one DB server will be affected. |
972 | * See https://www.mediawiki.org/wiki/Database_transactions for details. |
973 | * |
974 | * This is suitable for transactions that need to be serialized using cooperative locks, |
975 | * where each transaction can see each others' changes. Any transaction is flushed to clear |
976 | * out stale REPEATABLE-READ snapshot data. Once the returned object falls out of PHP scope, |
977 | * the lock will be released unless a transaction is active. If one is active, then the lock |
978 | * will be released when it either commits or rolls back. |
979 | * |
980 | * If the lock acquisition failed, then no transaction flush happens, and null is returned. |
981 | * |
982 | * @param string $lockKey Name of lock to release |
983 | * @param string $fname Name of the calling method |
984 | * @param int $timeout Acquisition timeout in seconds |
985 | * @return ScopedCallback|null |
986 | * @throws DBError If an error occurs, {@see query} |
987 | * @since 1.27 |
988 | */ |
989 | public function getScopedLockAndFlush( $lockKey, $fname, $timeout ); |
990 | |
991 | /** |
992 | * Check if this DB server is marked as read-only according to load balancer info |
993 | * |
994 | * @note LoadBalancer checks serverIsReadOnly() when setting the load balancer info array |
995 | * |
996 | * @return bool |
997 | * @since 1.27 |
998 | */ |
999 | public function isReadOnly(); |
1000 | } |