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