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