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 level (1 or 0)
88     * @internal For use in the rdbms library only
89     */
90    public const LB_TRX_ROUND_LEVEL = 'trxRoundLevel';
91    /**
92     * Field for getLBInfo()/setLBInfo(); relevant transaction round owner name or null
93     * @internal For use in the rdbms library only
94     */
95    public const LB_TRX_ROUND_FNAME = 'trxRoundOwner';
96    /**
97     * Field for getLBInfo()/setLBInfo(); configured read-only mode explanation or false
98     * @internal For use in the rdbms library only
99     */
100    public const LB_READ_ONLY_REASON = 'readOnlyReason';
101    /**
102     * Alias to LB_TRX_ROUND_FNAME
103     * @deprecated Since 1.44
104     */
105    public const LB_TRX_ROUND_ID = self::LB_TRX_ROUND_FNAME;
106
107    /** Primary server than can stream writes to replica servers */
108    public const ROLE_STREAMING_MASTER = 'streaming-master';
109    /** Replica server that receives writes from a primary server */
110    public const ROLE_STREAMING_REPLICA = 'streaming-replica';
111    /** Replica server within a static dataset */
112    public const ROLE_STATIC_CLONE = 'static-clone';
113    /** Server with unknown topology role */
114    public const ROLE_UNKNOWN = 'unknown';
115
116    /**
117     * Gets the current transaction level.
118     *
119     * Historically, transactions were allowed to be "nested". This is no
120     * longer supported, so this function really only returns a boolean.
121     *
122     * @return int The previous value
123     */
124    public function trxLevel();
125
126    /**
127     * Get the UNIX timestamp of the time that the transaction was established
128     *
129     * This can be used to reason about the staleness of SELECT data in REPEATABLE-READ
130     * transaction isolation level. Callers can assume that if a view-snapshot isolation
131     * is used, then the data read by SQL queries is *at least* up to date to that point
132     * (possibly more up-to-date since the first SELECT defines the snapshot).
133     *
134     * @return float|null Returns null if there is not active transaction
135     * @since 1.25
136     */
137    public function trxTimestamp();
138
139    /**
140     * Check whether there is a transaction open at the specific request of a caller
141     *
142     * Explicit transactions are spawned by begin(), startAtomic(), and doAtomicSection().
143     * Note that explicit transactions should not be confused with explicit transaction rounds.
144     *
145     * @return bool
146     * @since 1.28
147     */
148    public function explicitTrxActive();
149
150    /**
151     * Get properties passed down from the server info array of the load balancer
152     *
153     * @internal should not be called outside of rdbms library.
154     *
155     * @param string|null $name The entry of the info array to get, or null to get the whole array
156     * @return array|mixed|null
157     */
158    public function getLBInfo( $name = null );
159
160    /**
161     * Get the sequence-based ID assigned by the last query method call
162     *
163     * This method should only be called when all the following hold true:
164     *   - (a) A method call was made to insert(), upsert(), replace(), or insertSelect()
165     *   - (b) The method call attempts to insert exactly one row
166     *   - (c) The method call omits the value of exactly one auto-increment column
167     *   - (d) The method call succeeded
168     *   - (e) No subsequent method calls were made, with the exception of affectedRows(),
169     *         lastErrno(), lastError(), and getType()
170     *
171     * In all other cases, the return value is unspecified.
172     *
173     * When the query method is either insert() with "IGNORE", upsert(), or insertSelect(),
174     * callers should first check affectedRows() before calling this method, making sure that
175     * the query method actually created a row. Otherwise, an ID from a previous insert might
176     * be incorrectly assumed to belong to last insert.
177     *
178     * @return int
179     */
180    public function insertId();
181
182    /**
183     * Get the number of rows affected by the last query method call
184     *
185     * This method should only be called when all the following hold true:
186     *   - (a) A method call was made to insert(), upsert(), replace(), update(), delete(),
187     *         insertSelect(), query() with a non-SELECT statement, or queryMulti() with a
188     *         non-SELECT terminal statement
189     *   - (b) The method call succeeded
190     *   - (c) No subsequent method calls were made, with the exception of affectedRows(),
191     *         lastErrno(), lastError(), and getType()
192     *
193     * In all other cases, the return value is unspecified.
194     *
195     * UPDATE queries consider rows affected even when all their new column values match
196     * the previous values. Such rows can be excluded from the count by changing the WHERE
197     * clause to filter them out.
198     *
199     * If the last query method call was to query() or queryMulti(), then the results
200     * are based on the (last) statement provided to that call and are driver-specific.
201     *
202     * @return int
203     */
204    public function affectedRows();
205
206    /**
207     * Run an SQL query statement and return the result
208     *
209     * If a connection loss is detected, then an attempt to reconnect will be made.
210     * For queries that involve no larger transactions or locks, they will be re-issued
211     * for convenience, provided the connection was re-established.
212     *
213     * In new code, the query wrappers select(), insert(), update(), delete(),
214     * etc. should be used where possible, since they give much better DBMS
215     * independence and automatically quote or validate user input in a variety
216     * of contexts. This function is generally only useful for queries which are
217     * explicitly DBMS-dependent and are unsupported by the query wrappers, such
218     * as CREATE TABLE.
219     *
220     * However, the query wrappers themselves should call this function.
221     *
222     * Callers should avoid the use of statements like BEGIN, COMMIT, and ROLLBACK.
223     * Methods like startAtomic(), endAtomic(), and cancelAtomic() can be used instead.
224     *
225     * @param string|Query $sql Single-statement SQL query
226     * @param-taint $sql exec_sql
227     * @param string $fname Caller name; used for profiling/SHOW PROCESSLIST comments @phan-mandatory-param
228     * @param int $flags Bit field of ISQLPlatform::QUERY_* constants
229     * @return bool|IResultWrapper True for a successful write query, IResultWrapper object
230     *     for a successful read query, or false on failure if QUERY_SILENCE_ERRORS is set
231     * @return-taint tainted
232     * @throws DBQueryError If the query is issued, fails, and QUERY_SILENCE_ERRORS is not set
233     * @throws DBExpectedError If the query is not, and cannot, be issued yet (non-DBQueryError)
234     * @throws DBError If the query is inherently not allowed (non-DBExpectedError)
235     */
236    public function query( $sql, $fname = __METHOD__, $flags = 0 );
237
238    /**
239     * Get an UpdateQueryBuilder bound to this connection. This is overridden by
240     * DBConnRef.
241     *
242     * @note A new query builder must be created per query. Query builders
243     *   should not be reused since this uses a fluent interface and the state of
244     *   the builder changes during the query which may cause unexpected results.
245     *
246     * @return UpdateQueryBuilder
247     */
248    public function newUpdateQueryBuilder(): UpdateQueryBuilder;
249
250    /**
251     * Get an DeleteQueryBuilder bound to this connection. This is overridden by
252     * DBConnRef.
253     *
254     * @note A new query builder must be created per query. Query builders
255     *   should not be reused since this uses a fluent interface and the state of
256     *   the builder changes during the query which may cause unexpected results.
257     *
258     * @return DeleteQueryBuilder
259     */
260    public function newDeleteQueryBuilder(): DeleteQueryBuilder;
261
262    /**
263     * Get an InsertQueryBuilder bound to this connection. This is overridden by
264     * DBConnRef.
265     *
266     * @note A new query builder must be created per query. Query builders
267     *   should not be reused since this uses a fluent interface and the state of
268     *   the builder changes during the query which may cause unexpected results.
269     *
270     * @return InsertQueryBuilder
271     */
272    public function newInsertQueryBuilder(): InsertQueryBuilder;
273
274    /**
275     * Get an ReplaceQueryBuilder bound to this connection. This is overridden by
276     * DBConnRef.
277     *
278     * @note A new query builder must be created per query. Query builders
279     *   should not be reused since this uses a fluent interface and the state of
280     *   the builder changes during the query which may cause unexpected results.
281     *
282     * @return ReplaceQueryBuilder
283     */
284    public function newReplaceQueryBuilder(): ReplaceQueryBuilder;
285
286    /**
287     * Lock all rows meeting the given conditions/options FOR UPDATE
288     *
289     * @param string|string[] $table The unqualified name of table(s) (use an array for a join)
290     * @phpcs:ignore Generic.Files.LineLength
291     * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds
292     *   Condition in the format of IDatabase::select() conditions
293     * @param string $fname Function name for profiling @phan-mandatory-param
294     * @param array $options Options for select ("FOR UPDATE" is added automatically)
295     * @param array $join_conds Join conditions
296     * @return int Number of matching rows found (and locked)
297     * @throws DBError If an error occurs, {@see query}
298     * @since 1.32
299     * @deprecated since 1.43; Use SelectQueryBuilder::acquireRowLocks
300     */
301    public function lockForUpdate(
302        $table, $conds = '', $fname = __METHOD__, $options = [], $join_conds = []
303    );
304
305    /**
306     * Insert row(s) into a table, in the provided order
307     *
308     * This operation will be seen by affectedRows()/insertId() as one query statement,
309     * regardless of how many statements are actually sent by the class implementation.
310     *
311     * @internal callers outside of rdbms library should use InsertQueryBuilder instead.
312     *
313     * @param string $table The unqualified name of a table
314     * @param array|array[] $rows Row(s) to insert, as either:
315     *   - A string-keyed map of (column name => value) defining a new row. Values are
316     *     treated as literals and quoted appropriately; null is interpreted as NULL.
317     *   - An integer-keyed list of such string-keyed maps, defining a list of new rows.
318     *     The keys in each map must be identical to each other and in the same order.
319     *     The rows must not collide with each other.
320     * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param
321     * @param string|array $options Combination map/list where each string-keyed entry maps
322     *   a non-boolean option to the option parameters and each integer-keyed value is the
323     *   name of a boolean option. Supported options are:
324     *     - IGNORE: Boolean: skip insertion of rows that would cause unique key conflicts.
325     *       IDatabase::affectedRows() can be used to determine how many rows were inserted.
326     * @return bool Return true if no exception was thrown (deprecated since 1.33)
327     * @throws DBError If an error occurs, {@see query}
328     */
329    public function insert( $table, $rows, $fname = __METHOD__, $options = [] );
330
331    /**
332     * Update all rows in a table that match a given condition
333     *
334     * This operation will be seen by affectedRows()/insertId() as one query statement,
335     * regardless of how many statements are actually sent by the class implementation.
336     *
337     * @internal callers outside of rdbms library should use UpdateQueryBuilder instead.
338     *
339     * @param string $table The unqualified name of a table
340     * @param-taint $table exec_sql
341     * @param array<string,?scalar|RawSQLValue>|array<int,string> $set
342     *   Combination map/list where each string-keyed entry maps a column
343     *   to a literal assigned value and each integer-keyed value is a SQL expression in the
344     *   format of a column assignment within UPDATE...SET. The (column => value) entries are
345     *   convenient due to automatic value quoting and conversion of null to NULL. The SQL
346     *   assignment format is useful for updates like "column = column + X". All assignments
347     *   have no defined execution order, so they should not depend on each other. Do not
348     *   modify AUTOINCREMENT or UUID columns in assignments.
349     * @param-taint $set exec_sql_numkey
350     * @phpcs:ignore Generic.Files.LineLength
351     * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds
352     *   Condition in the format of IDatabase::select() conditions.
353     *   In order to prevent possible performance or replication issues or damaging a data
354     *   accidentally, an empty condition for 'update' queries isn't allowed.
355     *   IDatabase::ALL_ROWS should be passed explicitly in order to update all rows.
356     * @param-taint $conds exec_sql_numkey
357     * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param
358     * @param-taint $fname exec_sql
359     * @param string|array $options Combination map/list where each string-keyed entry maps
360     *   a non-boolean option to the option parameters and each integer-keyed value is the
361     *   name of a boolean option. Supported options are:
362     *     - IGNORE: Boolean: skip update of rows that would cause unique key conflicts.
363     *       IDatabase::affectedRows() includes all matching rows,
364     *       that includes also rows not updated due to key conflict.
365     * @param-taint $options none
366     * @return bool Return true if no exception was thrown (deprecated since 1.33)
367     * @return-taint none
368     * @throws DBError If an error occurs, {@see query}
369     */
370    public function update( $table, $set, $conds, $fname = __METHOD__, $options = [] );
371
372    /**
373     * Insert row(s) into a table, in the provided order, while deleting conflicting rows
374     *
375     * Conflicts are determined by the provided unique indexes. Note that it is possible
376     * for the provided rows to conflict even among themselves; it is preferable for the
377     * caller to de-duplicate such input beforehand.
378     *
379     * Note some important implications of the deletion semantics:
380     *   - If the table has an AUTOINCREMENT column and $rows omit that column, then any
381     *     conflicting existing rows will be replaced with newer having higher values for
382     *     that column, even if nothing else changed.
383     *   - There might be worse contention than upsert() due to the use of gap-locking.
384     *     This does not apply to RDBMS types that use predicate locking nor those that
385     *     just lock the whole table or databases anyway.
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 ReplaceQueryBuilder instead.
391     *
392     * @param string $table The unqualified name of a table
393     * @param string|string[]|string[][] $uniqueKeys Column name or non-empty list of column
394     *   name lists that define all applicable unique keys on the table. There must only be
395     *   one such key. Each unique key on the table is "applicable" unless either:
396     *     - It involves an AUTOINCREMENT column for which no values are assigned in $rows
397     *     - It involves a UUID column for which newly generated UUIDs are assigned in $rows
398     * @param array|array[] $rows Row(s) to insert, in the form of either:
399     *   - A string-keyed map of (column name => value) defining a new row. Values are
400     *     treated as literals and quoted appropriately; null is interpreted as NULL.
401     *     Columns belonging to a key in $uniqueKeys must be defined here and non-null.
402     *   - An integer-keyed list of such string-keyed maps, defining a list of new rows.
403     *     The keys in each map must be identical to each other and in the same order.
404     *     The rows must not collide with each other.
405     * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param
406     * @throws DBError If an error occurs, {@see query}
407     */
408    public function replace( $table, $uniqueKeys, $rows, $fname = __METHOD__ );
409
410    /**
411     * Upsert row(s) into a table, in the provided order, while updating conflicting rows
412     *
413     * Conflicts are determined by the provided unique indexes. Note that it is possible
414     * for the provided rows to conflict even among themselves; it is preferable for the
415     * caller to de-duplicate such input beforehand.
416     *
417     * This operation will be seen by affectedRows()/insertId() as one query statement,
418     * regardless of how many statements are actually sent by the class implementation.
419     *
420     * @internal callers outside of rdbms library should use InsertQueryBuilder instead.
421     *
422     * @param string $table The unqualified name of a table
423     * @param array|array[] $rows Row(s) to insert, in the form of either:
424     *   - A string-keyed map of (column name => value) defining a new row. Values are
425     *     treated as literals and quoted appropriately; null is interpreted as NULL.
426     *     Columns belonging to a key in $uniqueKeys must be defined here and non-null.
427     *   - An integer-keyed list of such string-keyed maps, defining a list of new rows.
428     *     The keys in each map must be identical to each other and in the same order.
429     *     The rows must not collide with each other.
430     * @param string|string[]|string[][] $uniqueKeys Column name or non-empty list of column
431     *   name lists that define all applicable unique keys on the table. There must only be
432     *   one such key. Each unique key on the table is "applicable" unless either:
433     *     - It involves an AUTOINCREMENT column for which no values are assigned in $rows
434     *     - It involves a UUID column for which newly generated UUIDs are assigned in $rows
435     * @param array<string,?scalar|RawSQLValue>|array<int,string> $set
436     *   Combination map/list where each string-keyed entry maps a column
437     *   to a literal assigned value and each integer-keyed value is a SQL assignment expression
438     *   of the form "<unquoted alphanumeric column> = <SQL expression>". The (column => value)
439     *   entries are convenient due to automatic value quoting and conversion of null to NULL.
440     *   The SQL assignment entries are useful for updates like "column = column + X". All of
441     *   the assignments have no defined execution order, so callers should make sure that they
442     *   not depend on each other. Do not modify AUTOINCREMENT or UUID columns in assignments,
443     *   even if they are just "secondary" unique keys. For multi-row upserts, use
444     *   buildExcludedValue() to reference the value of a column from the corresponding row
445     *   in $rows that conflicts with the current row.
446     * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param
447     * @throws DBError If an error occurs, {@see query}
448     * @since 1.22
449     */
450    public function upsert(
451        $table, array $rows, $uniqueKeys, array $set, $fname = __METHOD__
452    );
453
454    /**
455     * Delete all rows in a table that match a condition which includes a join
456     *
457     * For safety, an empty $conds will not delete everything. If you want to
458     * delete all rows where the join condition matches, set $conds=IDatabase::ALL_ROWS.
459     *
460     * DO NOT put the join condition in $conds.
461     *
462     * This operation will be seen by affectedRows()/insertId() as one query statement,
463     * regardless of how many statements are actually sent by the class implementation.
464     *
465     * @param string $delTable The unqualified name of the table to delete rows from.
466     * @param string $joinTable The unqualified name of the reference table to join on.
467     * @param string $delVar The variable to join on, in the first table.
468     * @param string $joinVar The variable to join on, in the second table.
469     * @phpcs:ignore Generic.Files.LineLength
470     * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds
471     *   Condition array of field names mapped to variables,
472     *   ANDed together in the WHERE clause
473     * @param string $fname Calling function name (use __METHOD__) for logs/profiling @phan-mandatory-param
474     * @throws DBError If an error occurs, {@see query}
475     */
476    public function deleteJoin(
477        $delTable,
478        $joinTable,
479        $delVar,
480        $joinVar,
481        $conds,
482        $fname = __METHOD__
483    );
484
485    /**
486     * Delete all rows in a table that match a condition
487     *
488     * This operation will be seen by affectedRows()/insertId() as one query statement,
489     * regardless of how many statements are actually sent by the class implementation.
490     *
491     * @internal callers outside of rdbms library should use DeleteQueryBuilder instead.
492     *
493     * @param string $table The unqualified name of a table
494     * @param-taint $table exec_sql
495     * @phpcs:ignore Generic.Files.LineLength
496     * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds
497     *   Array of conditions. See $conds in IDatabase::select()
498     *   In order to prevent possible performance or replication issues or damaging a data
499     *   accidentally, an empty condition for 'delete' queries isn't allowed.
500     *   IDatabase::ALL_ROWS should be passed explicitly in order to delete all rows.
501     * @param-taint $conds exec_sql_numkey
502     * @param string $fname Name of the calling function @phan-mandatory-param
503     * @param-taint $fname exec_sql
504     * @return bool Return true if no exception was thrown (deprecated since 1.33)
505     * @return-taint none
506     * @throws DBError If an error occurs, {@see query}
507     */
508    public function delete( $table, $conds, $fname = __METHOD__ );
509
510    /**
511     * INSERT SELECT wrapper
512     *
513     * @warning If the insert will use an auto-increment or sequence to
514     *  determine the value of a column, this may break replication on
515     *  databases using statement-based replication if the SELECT is not
516     *  deterministically ordered.
517     *
518     * This operation will be seen by affectedRows()/insertId() as one query statement,
519     * regardless of how many statements are actually sent by the class implementation.
520     *
521     * @param string $destTable Unqualified name of destination table
522     * @param string|array $srcTable Unqualified name of source table(s) (use an array for a join)
523     * @param array $varMap Must be an associative array of the form
524     *    [ 'dest1' => 'source1', ... ]. Source items may be literals
525     *    rather than field names, but strings should be quoted with
526     *    IDatabase::addQuotes()
527     * @phpcs:ignore Generic.Files.LineLength
528     * @param string|IExpression|array<string,?scalar|non-empty-array<int,?scalar>|RawSQLValue>|array<int,string|IExpression> $conds
529     *    Condition array. See $conds in IDatabase::select() for
530     *    the details of the format of condition arrays. May be "*" to copy the
531     *    whole table.
532     * @param string $fname The function name of the caller, from __METHOD__ @phan-mandatory-param
533     * @param array $insertOptions Options for the INSERT part of the query, see
534     *    IDatabase::insert() for details. Also, one additional option is
535     *    available: pass 'NO_AUTO_COLUMNS' to hint that the query does not use
536     *    an auto-increment or sequence to determine any column values.
537     * @param array $selectOptions Options for the SELECT part of the query, see
538     *    IDatabase::select() for details.
539     * @param array $selectJoinConds Join conditions for the SELECT part of the query, see
540     *    IDatabase::select() for details.
541     * @return bool Return true if no exception was thrown (deprecated since 1.33)
542     * @throws DBError If an error occurs, {@see query}
543     */
544    public function insertSelect(
545        $destTable,
546        $srcTable,
547        $varMap,
548        $conds,
549        $fname = __METHOD__,
550        $insertOptions = [],
551        $selectOptions = [],
552        $selectJoinConds = []
553    );
554
555    /**
556     * Run a callback when the current transaction commits or rolls back
557     *
558     * An error is thrown if no transaction is pending.
559     *
560     * When transaction round mode (DBO_TRX) is set, the callback will run at the end
561     * of the round, just after all peer transactions COMMIT/ROLLBACK.
562     *
563     * This IDatabase instance will start off in auto-commit mode when the callback starts.
564     * The use of other IDatabase handles from the callback should be avoided unless they are
565     * known to be in auto-commit mode. Callbacks that create transactions via begin() or
566     * startAtomic() must have matching calls to commit()/endAtomic().
567     *
568     * Use this method only for the following purposes:
569     *   - (a) Release of cooperative locks on resources
570     *   - (b) Cancellation of in-process deferred tasks
571     *
572     * The callback takes the following arguments:
573     *   - How the current atomic section (if any) or overall transaction (otherwise) ended
574     *     (IDatabase::TRIGGER_COMMIT or IDatabase::TRIGGER_ROLLBACK)
575     *
576     * Callbacks will execute in the order they were enqueued.
577     *
578     * @param callable $callback
579     * @param string $fname Caller name @phan-mandatory-param
580     * @throws DBError If an error occurs, {@see query}
581     * @throws Exception If the callback runs immediately and an error occurs in it
582     * @since 1.28
583     */
584    public function onTransactionResolution( callable $callback, $fname = __METHOD__ );
585
586    /**
587     * Run a callback when the current transaction commits or now if there is none
588     *
589     * If there is a transaction and it is rolled back, then the callback is cancelled.
590     *
591     * When transaction round mode (DBO_TRX) is set, the callback will run at the end
592     * of the round, just after all peer transactions COMMIT. If the transaction round
593     * is rolled back, then the callback is cancelled.
594     *
595     * This IDatabase instance will start off in auto-commit mode when the callback starts.
596     * The use of other IDatabase handles from the callback should be avoided unless they are
597     * known to be in auto-commit mode. Callbacks that create transactions via begin() or
598     * startAtomic() must have matching calls to commit()/endAtomic().
599     *
600     * Use this method only for the following purposes:
601     *   - (a) RDBMS updates, prone to lock timeouts/deadlocks, that do not require
602     *         atomicity with respect to the updates in the current transaction (if any)
603     *   - (b) Purges to lightweight cache services due to RDBMS updates
604     *   - (c) Updates to secondary DBs/stores that must only commit once the updates in
605     *         the current transaction (if any) are committed (e.g. insert user account row
606     *         to DB1, then, initialize corresponding LDAP account)
607     *
608     * The callback takes the following arguments:
609     *   - How the transaction ended (IDatabase::TRIGGER_COMMIT or IDatabase::TRIGGER_IDLE)
610     *
611     * Callbacks will execute in the order they were enqueued.
612     *
613     * @param callable $callback
614     * @param string $fname Caller name @phan-mandatory-param
615     * @throws DBError If an error occurs, {@see query}
616     * @throws Exception If the callback runs immediately and an error occurs in it
617     * @since 1.32
618     */
619    public function onTransactionCommitOrIdle( callable $callback, $fname = __METHOD__ );
620
621    /**
622     * Run a callback before the current transaction commits or now if there is none
623     *
624     * If there is a transaction and it is rolled back, then the callback is cancelled.
625     *
626     * When transaction round mode (DBO_TRX) is set, the callback will run at the end
627     * of the round, just after all peer transactions COMMIT. If the transaction round
628     * is rolled back, then the callback is cancelled.
629     *
630     * If there is no current transaction, one will be created to wrap the callback.
631     * Callbacks cannot use begin()/commit() to manage transactions. The use of other
632     * IDatabase handles from the callback should be avoided.
633     *
634     * Use this method only for the following purposes:
635     *   - a) RDBMS updates, prone to lock timeouts/deadlocks, that require atomicity
636     *        with respect to the updates in the current transaction (if any)
637     *   - b) Purges to lightweight cache services due to RDBMS updates
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}