Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
20.26% |
46 / 227 |
|
5.23% |
8 / 153 |
CRAP | |
0.00% |
0 / 1 |
DBConnRef | |
20.26% |
46 / 227 |
|
5.23% |
8 / 153 |
15700.09 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
ensureConnection | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
5 | |||
__call | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getReferenceRole | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getServerInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getTopologyBasedServerId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getTopologyRole | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
trxLevel | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
trxTimestamp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
explicitTrxActive | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
tablePrefix | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
dbSchema | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
getLBInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setLBInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
implicitOrderby | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
lastDoneWrites | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
writesPending | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
writesOrCallbacksPending | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
pendingWriteQueryDuration | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
pendingWriteCallers | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isOpen | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setFlag | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
clearFlag | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
restoreFlags | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getFlag | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getProperty | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDomainID | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
2.15 | |||
getType | |
80.00% |
4 / 5 |
|
0.00% |
0 / 1 |
3.07 | |||
insertId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
lastErrno | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
lastError | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
affectedRows | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSoftwareLink | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getServerVersion | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
close | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
query | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
newSelectQueryBuilder | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
newUnionQueryBuilder | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
newUpdateQueryBuilder | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
newDeleteQueryBuilder | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
newInsertQueryBuilder | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
newReplaceQueryBuilder | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
selectField | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
selectFieldValues | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
select | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
selectSQLText | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
limitResult | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
selectRow | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
estimateRowCount | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
selectRowCount | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
lockForUpdate | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
fieldExists | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
indexExists | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
tableExists | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
insert | |
50.00% |
1 / 2 |
|
0.00% |
0 / 1 |
1.12 | |||
update | |
50.00% |
1 / 2 |
|
0.00% |
0 / 1 |
1.12 | |||
buildComparison | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
makeList | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
makeWhereFrom2d | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
factorConds | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
bitNot | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
bitAnd | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
bitOr | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildConcat | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildGroupConcatField | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildGreatest | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildLeast | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildSubstring | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildStringCast | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildIntegerCast | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildExcludedValue | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildSelectSubquery | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
databasesAreIndependent | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
selectDomain | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDBname | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getServer | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getServerName | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
12 | |||
addQuotes | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
expr | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
addIdentifierQuotes | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
buildLike | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
anyChar | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
anyString | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
nextSequenceValue | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
replace | |
50.00% |
1 / 2 |
|
0.00% |
0 / 1 |
1.12 | |||
upsert | |
50.00% |
1 / 2 |
|
0.00% |
0 / 1 |
1.12 | |||
deleteJoin | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
delete | |
50.00% |
1 / 2 |
|
0.00% |
0 / 1 |
1.12 | |||
insertSelect | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
unionSupportsOrderAndLimit | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
unionQueries | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
conditional | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
strreplace | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
wasDeadlock | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
wasReadOnlyError | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
primaryPosWait | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getReplicaPos | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getPrimaryPos | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
serverIsReadOnly | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onTransactionResolution | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onTransactionCommitOrIdle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onTransactionPreCommitOrIdle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
onAtomicSectionCancel | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setTransactionListener | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
startAtomic | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
endAtomic | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
cancelAtomic | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
doAtomicSection | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
begin | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
commit | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
rollback | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
flushSession | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
flushSnapshot | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
timestamp | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
timestampOrNull | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
ping | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getLag | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getSessionLagStatus | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
encodeBlob | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
decodeBlob | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setSessionOptions | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setSchemaVars | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
lockIsFree | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
lock | |
50.00% |
1 / 2 |
|
0.00% |
0 / 1 |
1.12 | |||
unlock | |
50.00% |
1 / 2 |
|
0.00% |
0 / 1 |
1.12 | |||
getScopedLockAndFlush | |
50.00% |
1 / 2 |
|
0.00% |
0 / 1 |
1.12 | |||
namedLocksEnqueue | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getInfinity | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
encodeExpiry | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
decodeExpiry | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isReadOnly | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setTableAliases | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getTableAliases | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setIndexAliases | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
tableName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
tableNames | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
tableNamesN | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
sourceFile | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
sourceStream | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
dropTable | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
truncateTable | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
truncate | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
listViews | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
textFieldSize | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
streamStatementEnd | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
duplicateTableStructure | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
indexUnique | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
listTables | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
fieldInfo | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
__toString | |
66.67% |
2 / 3 |
|
0.00% |
0 / 1 |
2.15 | |||
assertRoleAllowsWrites | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
getDomainChangeException | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
normalizeServerIndex | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Wikimedia\Rdbms; |
4 | |
5 | use InvalidArgumentException; |
6 | |
7 | /** |
8 | * Helper class used for automatically re-using IDatabase connections and lazily |
9 | * establishing the actual network connection to a database host. |
10 | * |
11 | * It does this by deferring to ILoadBalancer::getConnectionInternal, which in |
12 | * turn ensures we share and re-use a single connection for a given database |
13 | * wherever possible. |
14 | * |
15 | * This class previously used an RAII-style pattern where connections would be |
16 | * claimed from a pool, and then added back to the pool for re-use only after |
17 | * the calling code's variable for this object went out of scope (a __destruct |
18 | * got called when the calling function returns or throws). This is no longer |
19 | * needed today as LoadBalancer now permits re-use internally even for |
20 | * overlapping callers, where two pieces of code may both obtain their own |
21 | * DBConnRef object and where both are used alternatingly, and yet still share |
22 | * the same connection. |
23 | * |
24 | * @par Example: |
25 | * @code |
26 | * function getRowData() { |
27 | * $conn = $this->lb->getConnection( DB_REPLICA ); |
28 | * $row = $conn->select( ... ); |
29 | * return $row ? (array)$row : false; |
30 | * } |
31 | * @endcode |
32 | * |
33 | * @ingroup Database |
34 | * @since 1.22 |
35 | */ |
36 | class DBConnRef implements IMaintainableDatabase { |
37 | /** @var ILoadBalancer */ |
38 | private $lb; |
39 | /** @var Database|null Live connection handle */ |
40 | private $conn; |
41 | /** |
42 | * @var array Map of (DBConnRef::FLD_* constant => connection parameter) |
43 | * @phan-var array{0:int,1:array|string|false,2:DatabaseDomain,3:int} |
44 | */ |
45 | private $params; |
46 | /** @var int One of DB_PRIMARY/DB_REPLICA */ |
47 | private $role; |
48 | |
49 | /** |
50 | * @var int Reference to the $modcount passed to the constructor. |
51 | * $conn is valid if $modCountRef and $modCountFix are the same. |
52 | */ |
53 | private $modCountRef; |
54 | |
55 | /** |
56 | * @var int Last known good value of $modCountRef |
57 | * $conn is valid if $modCountRef and $modCountFix are the same. |
58 | */ |
59 | private $modCountFix; |
60 | |
61 | private const FLD_INDEX = 0; |
62 | private const FLD_GROUPS = 1; |
63 | private const FLD_DOMAIN = 2; |
64 | private const FLD_FLAGS = 3; |
65 | |
66 | /** |
67 | * @internal May not be used outside Rdbms LoadBalancer |
68 | * @param ILoadBalancer $lb Connection manager for $conn |
69 | * @param array $params [server index, query groups, domain, flags] |
70 | * @param int $role The type of connection asked for; one of DB_PRIMARY/DB_REPLICA |
71 | * @param null|int &$modcount Reference to a modification counter. This is for |
72 | * LoadBalancer::reconfigure to indicate that a new connection should be acquired. |
73 | */ |
74 | public function __construct( ILoadBalancer $lb, $params, $role, &$modcount = 0 ) { |
75 | if ( !is_array( $params ) || count( $params ) < 4 || $params[self::FLD_DOMAIN] === false ) { |
76 | throw new InvalidArgumentException( "Missing lazy connection arguments." ); |
77 | } |
78 | |
79 | $params[self::FLD_DOMAIN] = DatabaseDomain::newFromId( $params[self::FLD_DOMAIN] ); |
80 | |
81 | $this->lb = $lb; |
82 | $this->params = $params; |
83 | $this->role = $role; |
84 | |
85 | // $this->conn is valid as long as $this->modCountRef and $this->modCountFix are the same. |
86 | $this->modCountRef = &$modcount; // remember reference |
87 | $this->modCountFix = $modcount; // remember current value |
88 | } |
89 | |
90 | /** |
91 | * Connect to the database if we are not already connected. |
92 | */ |
93 | public function ensureConnection() { |
94 | if ( $this->modCountFix !== $this->modCountRef ) { |
95 | // Discard existing connection, unless we are in an ongoing transaction. |
96 | // This is triggered by LoadBalancer::reconfigure(), to allow changed settings |
97 | // to take effect. The primary use case are replica servers being taken out of |
98 | // rotation, or the primary database changing. |
99 | if ( !$this->conn->trxLevel() ) { |
100 | $this->conn->close(); |
101 | $this->conn = null; |
102 | } |
103 | } |
104 | |
105 | if ( $this->conn === null ) { |
106 | $this->conn = $this->lb->getConnectionInternal( |
107 | $this->params[self::FLD_INDEX], |
108 | $this->params[self::FLD_GROUPS], |
109 | $this->params[self::FLD_DOMAIN]->getId(), |
110 | $this->params[self::FLD_FLAGS] |
111 | ); |
112 | $this->modCountFix = $this->modCountRef; |
113 | } |
114 | |
115 | if ( !$this->params[self::FLD_DOMAIN]->equals( $this->conn->getDomainID() ) ) { |
116 | // The underlying connection handle is likely being shared by other DBConnRef |
117 | // instances in a load balancer. Make sure that each one routes queries by their |
118 | // owner function to the domain that the owner expects. |
119 | $this->conn->selectDomain( $this->params[self::FLD_DOMAIN] ); |
120 | } |
121 | } |
122 | |
123 | public function __call( $name, array $arguments ) { |
124 | $this->ensureConnection(); |
125 | |
126 | return $this->conn->$name( ...$arguments ); |
127 | } |
128 | |
129 | /** |
130 | * @return int DB_PRIMARY when this *requires* the primary DB, otherwise DB_REPLICA |
131 | * @since 1.33 |
132 | */ |
133 | public function getReferenceRole() { |
134 | return $this->role; |
135 | } |
136 | |
137 | public function getServerInfo() { |
138 | return $this->__call( __FUNCTION__, func_get_args() ); |
139 | } |
140 | |
141 | public function getTopologyBasedServerId() { |
142 | return $this->__call( __FUNCTION__, func_get_args() ); |
143 | } |
144 | |
145 | public function getTopologyRole() { |
146 | return $this->__call( __FUNCTION__, func_get_args() ); |
147 | } |
148 | |
149 | public function trxLevel() { |
150 | return $this->__call( __FUNCTION__, func_get_args() ); |
151 | } |
152 | |
153 | public function trxTimestamp() { |
154 | return $this->__call( __FUNCTION__, func_get_args() ); |
155 | } |
156 | |
157 | public function explicitTrxActive() { |
158 | return $this->__call( __FUNCTION__, func_get_args() ); |
159 | } |
160 | |
161 | public function tablePrefix( $prefix = null ) { |
162 | if ( $prefix !== null ) { |
163 | // Disallow things that might confuse the LoadBalancer tracking |
164 | throw $this->getDomainChangeException(); |
165 | } |
166 | |
167 | if ( $this->conn === null ) { |
168 | // Avoid triggering a database connection |
169 | $prefix = $this->params[self::FLD_DOMAIN]->getTablePrefix(); |
170 | } else { |
171 | // This will just return the prefix |
172 | $prefix = $this->__call( __FUNCTION__, func_get_args() ); |
173 | } |
174 | |
175 | return $prefix; |
176 | } |
177 | |
178 | public function dbSchema( $schema = null ) { |
179 | if ( $schema !== null ) { |
180 | // Disallow things that might confuse the LoadBalancer tracking |
181 | throw $this->getDomainChangeException(); |
182 | } |
183 | |
184 | if ( $this->conn === null ) { |
185 | // Avoid triggering a database connection |
186 | $schema = (string)( $this->params[self::FLD_DOMAIN]->getSchema() ); |
187 | } else { |
188 | // This will just return the schema |
189 | $schema = $this->__call( __FUNCTION__, func_get_args() ); |
190 | } |
191 | |
192 | return $schema; |
193 | } |
194 | |
195 | public function getLBInfo( $name = null ) { |
196 | return $this->__call( __FUNCTION__, func_get_args() ); |
197 | } |
198 | |
199 | public function setLBInfo( $nameOrArray, $value = null ) { |
200 | // @phan-suppress-previous-line PhanPluginNeverReturnMethod |
201 | // Disallow things that might confuse the LoadBalancer tracking |
202 | throw $this->getDomainChangeException(); |
203 | } |
204 | |
205 | public function implicitOrderby() { |
206 | return $this->__call( __FUNCTION__, func_get_args() ); |
207 | } |
208 | |
209 | public function lastDoneWrites() { |
210 | return $this->__call( __FUNCTION__, func_get_args() ); |
211 | } |
212 | |
213 | public function writesPending() { |
214 | return $this->__call( __FUNCTION__, func_get_args() ); |
215 | } |
216 | |
217 | public function writesOrCallbacksPending() { |
218 | return $this->__call( __FUNCTION__, func_get_args() ); |
219 | } |
220 | |
221 | public function pendingWriteQueryDuration( $type = self::ESTIMATE_TOTAL ) { |
222 | return $this->__call( __FUNCTION__, func_get_args() ); |
223 | } |
224 | |
225 | public function pendingWriteCallers() { |
226 | return $this->__call( __FUNCTION__, func_get_args() ); |
227 | } |
228 | |
229 | public function isOpen() { |
230 | return $this->__call( __FUNCTION__, func_get_args() ); |
231 | } |
232 | |
233 | public function setFlag( $flag, $remember = self::REMEMBER_NOTHING ) { |
234 | return $this->__call( __FUNCTION__, func_get_args() ); |
235 | } |
236 | |
237 | public function clearFlag( $flag, $remember = self::REMEMBER_NOTHING ) { |
238 | return $this->__call( __FUNCTION__, func_get_args() ); |
239 | } |
240 | |
241 | public function restoreFlags( $state = self::RESTORE_PRIOR ) { |
242 | return $this->__call( __FUNCTION__, func_get_args() ); |
243 | } |
244 | |
245 | public function getFlag( $flag ) { |
246 | return $this->__call( __FUNCTION__, func_get_args() ); |
247 | } |
248 | |
249 | public function getProperty( $name ) { |
250 | return $this->__call( __FUNCTION__, func_get_args() ); |
251 | } |
252 | |
253 | public function getDomainID() { |
254 | if ( $this->conn === null ) { |
255 | // Avoid triggering a database connection |
256 | return $this->params[self::FLD_DOMAIN]->getId(); |
257 | } |
258 | |
259 | return $this->__call( __FUNCTION__, func_get_args() ); |
260 | } |
261 | |
262 | public function getType() { |
263 | if ( $this->conn === null ) { |
264 | // Avoid triggering a database connection |
265 | $index = $this->normalizeServerIndex( $this->params[self::FLD_INDEX] ); |
266 | if ( $index >= 0 ) { |
267 | // In theory, if $index is DB_REPLICA, the type could vary |
268 | return $this->lb->getServerType( $index ); |
269 | } |
270 | } |
271 | |
272 | return $this->__call( __FUNCTION__, func_get_args() ); |
273 | } |
274 | |
275 | public function insertId() { |
276 | return $this->__call( __FUNCTION__, func_get_args() ); |
277 | } |
278 | |
279 | public function lastErrno() { |
280 | return $this->__call( __FUNCTION__, func_get_args() ); |
281 | } |
282 | |
283 | public function lastError() { |
284 | return $this->__call( __FUNCTION__, func_get_args() ); |
285 | } |
286 | |
287 | public function affectedRows() { |
288 | return $this->__call( __FUNCTION__, func_get_args() ); |
289 | } |
290 | |
291 | public function getSoftwareLink() { |
292 | return $this->__call( __FUNCTION__, func_get_args() ); |
293 | } |
294 | |
295 | public function getServerVersion() { |
296 | return $this->__call( __FUNCTION__, func_get_args() ); |
297 | } |
298 | |
299 | public function close( $fname = __METHOD__ ) { |
300 | // @phan-suppress-previous-line PhanPluginNeverReturnMethod |
301 | throw new DBUnexpectedError( $this->conn, 'Cannot close shared connection.' ); |
302 | } |
303 | |
304 | public function query( $sql, $fname = __METHOD__, $flags = 0 ) { |
305 | if ( $this->role !== ILoadBalancer::DB_PRIMARY ) { |
306 | $flags |= IDatabase::QUERY_REPLICA_ROLE; |
307 | } |
308 | |
309 | return $this->__call( __FUNCTION__, [ $sql, $fname, $flags ] ); |
310 | } |
311 | |
312 | public function newSelectQueryBuilder(): SelectQueryBuilder { |
313 | // Use $this not $this->conn so that the domain is preserved (T326377) |
314 | return new SelectQueryBuilder( $this ); |
315 | } |
316 | |
317 | public function newUnionQueryBuilder(): UnionQueryBuilder { |
318 | // Use $this not $this->conn so that the domain is preserved (T326377) |
319 | return new UnionQueryBuilder( $this ); |
320 | } |
321 | |
322 | public function newUpdateQueryBuilder(): UpdateQueryBuilder { |
323 | // Use $this not $this->conn so that the domain is preserved (T326377) |
324 | return new UpdateQueryBuilder( $this ); |
325 | } |
326 | |
327 | public function newDeleteQueryBuilder(): DeleteQueryBuilder { |
328 | // Use $this not $this->conn so that the domain is preserved (T326377) |
329 | return new DeleteQueryBuilder( $this ); |
330 | } |
331 | |
332 | public function newInsertQueryBuilder(): InsertQueryBuilder { |
333 | // Use $this not $this->conn so that the domain is preserved (T326377) |
334 | return new InsertQueryBuilder( $this ); |
335 | } |
336 | |
337 | public function newReplaceQueryBuilder(): ReplaceQueryBuilder { |
338 | // Use $this not $this->conn so that the domain is preserved (T326377) |
339 | return new ReplaceQueryBuilder( $this ); |
340 | } |
341 | |
342 | public function selectField( |
343 | $table, $var, $cond = '', $fname = __METHOD__, $options = [], $join_conds = [] |
344 | ) { |
345 | return $this->__call( __FUNCTION__, func_get_args() ); |
346 | } |
347 | |
348 | public function selectFieldValues( |
349 | $table, $var, $cond = '', $fname = __METHOD__, $options = [], $join_conds = [] |
350 | ): array { |
351 | return $this->__call( __FUNCTION__, func_get_args() ); |
352 | } |
353 | |
354 | public function select( |
355 | $table, $vars, $conds = '', $fname = __METHOD__, |
356 | $options = [], $join_conds = [] |
357 | ) { |
358 | return $this->__call( __FUNCTION__, func_get_args() ); |
359 | } |
360 | |
361 | public function selectSQLText( |
362 | $table, $vars, $conds = '', $fname = __METHOD__, |
363 | $options = [], $join_conds = [] |
364 | ) { |
365 | return $this->__call( __FUNCTION__, func_get_args() ); |
366 | } |
367 | |
368 | public function limitResult( $sql, $limit, $offset = false ) { |
369 | return $this->__call( __FUNCTION__, func_get_args() ); |
370 | } |
371 | |
372 | public function selectRow( |
373 | $table, $vars, $conds, $fname = __METHOD__, |
374 | $options = [], $join_conds = [] |
375 | ) { |
376 | return $this->__call( __FUNCTION__, func_get_args() ); |
377 | } |
378 | |
379 | public function estimateRowCount( |
380 | $tables, $vars = '*', $conds = '', $fname = __METHOD__, $options = [], $join_conds = [] |
381 | ) { |
382 | return $this->__call( __FUNCTION__, func_get_args() ); |
383 | } |
384 | |
385 | public function selectRowCount( |
386 | $tables, $vars = '*', $conds = '', $fname = __METHOD__, $options = [], $join_conds = [] |
387 | ) { |
388 | return $this->__call( __FUNCTION__, func_get_args() ); |
389 | } |
390 | |
391 | public function lockForUpdate( |
392 | $table, $conds = '', $fname = __METHOD__, $options = [], $join_conds = [] |
393 | ) { |
394 | $this->assertRoleAllowsWrites(); |
395 | |
396 | return $this->__call( __FUNCTION__, func_get_args() ); |
397 | } |
398 | |
399 | public function fieldExists( $table, $field, $fname = __METHOD__ ) { |
400 | return $this->__call( __FUNCTION__, func_get_args() ); |
401 | } |
402 | |
403 | public function indexExists( $table, $index, $fname = __METHOD__ ) { |
404 | return $this->__call( __FUNCTION__, func_get_args() ); |
405 | } |
406 | |
407 | public function tableExists( $table, $fname = __METHOD__ ) { |
408 | return $this->__call( __FUNCTION__, func_get_args() ); |
409 | } |
410 | |
411 | public function insert( $table, $rows, $fname = __METHOD__, $options = [] ) { |
412 | $this->assertRoleAllowsWrites(); |
413 | |
414 | return $this->__call( __FUNCTION__, func_get_args() ); |
415 | } |
416 | |
417 | public function update( $table, $set, $conds, $fname = __METHOD__, $options = [] ) { |
418 | $this->assertRoleAllowsWrites(); |
419 | |
420 | return $this->__call( __FUNCTION__, func_get_args() ); |
421 | } |
422 | |
423 | public function buildComparison( string $op, array $conds ): string { |
424 | return $this->__call( __FUNCTION__, func_get_args() ); |
425 | } |
426 | |
427 | public function makeList( array $a, $mode = self::LIST_COMMA ) { |
428 | return $this->__call( __FUNCTION__, func_get_args() ); |
429 | } |
430 | |
431 | public function makeWhereFrom2d( $data, $baseKey, $subKey ) { |
432 | return $this->__call( __FUNCTION__, func_get_args() ); |
433 | } |
434 | |
435 | public function factorConds( $condsArray ) { |
436 | return $this->__call( __FUNCTION__, func_get_args() ); |
437 | } |
438 | |
439 | public function bitNot( $field ) { |
440 | return $this->__call( __FUNCTION__, func_get_args() ); |
441 | } |
442 | |
443 | public function bitAnd( $fieldLeft, $fieldRight ) { |
444 | return $this->__call( __FUNCTION__, func_get_args() ); |
445 | } |
446 | |
447 | public function bitOr( $fieldLeft, $fieldRight ) { |
448 | return $this->__call( __FUNCTION__, func_get_args() ); |
449 | } |
450 | |
451 | public function buildConcat( $stringList ) { |
452 | return $this->__call( __FUNCTION__, func_get_args() ); |
453 | } |
454 | |
455 | public function buildGroupConcatField( |
456 | $delim, $table, $field, $conds = '', $join_conds = [] |
457 | ) { |
458 | return $this->__call( __FUNCTION__, func_get_args() ); |
459 | } |
460 | |
461 | public function buildGreatest( $fields, $values ) { |
462 | return $this->__call( __FUNCTION__, func_get_args() ); |
463 | } |
464 | |
465 | public function buildLeast( $fields, $values ) { |
466 | return $this->__call( __FUNCTION__, func_get_args() ); |
467 | } |
468 | |
469 | public function buildSubstring( $input, $startPosition, $length = null ) { |
470 | return $this->__call( __FUNCTION__, func_get_args() ); |
471 | } |
472 | |
473 | public function buildStringCast( $field ) { |
474 | return $this->__call( __FUNCTION__, func_get_args() ); |
475 | } |
476 | |
477 | public function buildIntegerCast( $field ) { |
478 | return $this->__call( __FUNCTION__, func_get_args() ); |
479 | } |
480 | |
481 | public function buildExcludedValue( $column ) { |
482 | return $this->__call( __FUNCTION__, func_get_args() ); |
483 | } |
484 | |
485 | public function buildSelectSubquery( |
486 | $table, $vars, $conds = '', $fname = __METHOD__, |
487 | $options = [], $join_conds = [] |
488 | ) { |
489 | return $this->__call( __FUNCTION__, func_get_args() ); |
490 | } |
491 | |
492 | public function databasesAreIndependent() { |
493 | return $this->__call( __FUNCTION__, func_get_args() ); |
494 | } |
495 | |
496 | public function selectDomain( $domain ) { |
497 | // @phan-suppress-previous-line PhanPluginNeverReturnMethod |
498 | // Disallow things that might confuse the LoadBalancer tracking |
499 | throw $this->getDomainChangeException(); |
500 | } |
501 | |
502 | public function getDBname() { |
503 | if ( $this->conn === null ) { |
504 | // Avoid triggering a database connection |
505 | return $this->params[self::FLD_DOMAIN]->getDatabase(); |
506 | } |
507 | |
508 | return $this->__call( __FUNCTION__, func_get_args() ); |
509 | } |
510 | |
511 | public function getServer() { |
512 | return $this->__call( __FUNCTION__, func_get_args() ); |
513 | } |
514 | |
515 | public function getServerName() { |
516 | if ( $this->conn === null ) { |
517 | // Avoid triggering a database connection |
518 | $index = $this->normalizeServerIndex( $this->params[self::FLD_INDEX] ); |
519 | if ( $index >= 0 ) { |
520 | // If $index is DB_REPLICA, the server name could vary |
521 | return $this->lb->getServerName( $index ); |
522 | } |
523 | } |
524 | |
525 | return $this->__call( __FUNCTION__, func_get_args() ); |
526 | } |
527 | |
528 | public function addQuotes( $s ) { |
529 | return $this->__call( __FUNCTION__, func_get_args() ); |
530 | } |
531 | |
532 | public function expr( string $field, string $op, $value ): Expression { |
533 | return new Expression( $field, $op, $value ); |
534 | } |
535 | |
536 | public function addIdentifierQuotes( $s ) { |
537 | return $this->__call( __FUNCTION__, func_get_args() ); |
538 | } |
539 | |
540 | public function buildLike( $param, ...$params ) { |
541 | return $this->__call( __FUNCTION__, func_get_args() ); |
542 | } |
543 | |
544 | public function anyChar() { |
545 | return $this->__call( __FUNCTION__, func_get_args() ); |
546 | } |
547 | |
548 | public function anyString() { |
549 | return $this->__call( __FUNCTION__, func_get_args() ); |
550 | } |
551 | |
552 | public function nextSequenceValue( $seqName ) { |
553 | $this->assertRoleAllowsWrites(); |
554 | |
555 | return $this->__call( __FUNCTION__, func_get_args() ); |
556 | } |
557 | |
558 | public function replace( $table, $uniqueKeys, $rows, $fname = __METHOD__ ) { |
559 | $this->assertRoleAllowsWrites(); |
560 | |
561 | return $this->__call( __FUNCTION__, func_get_args() ); |
562 | } |
563 | |
564 | public function upsert( |
565 | $table, array $rows, $uniqueKeys, array $set, $fname = __METHOD__ |
566 | ) { |
567 | $this->assertRoleAllowsWrites(); |
568 | |
569 | return $this->__call( __FUNCTION__, func_get_args() ); |
570 | } |
571 | |
572 | public function deleteJoin( |
573 | $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = __METHOD__ |
574 | ) { |
575 | $this->assertRoleAllowsWrites(); |
576 | |
577 | $this->__call( __FUNCTION__, func_get_args() ); |
578 | } |
579 | |
580 | public function delete( $table, $conds, $fname = __METHOD__ ) { |
581 | $this->assertRoleAllowsWrites(); |
582 | |
583 | return $this->__call( __FUNCTION__, func_get_args() ); |
584 | } |
585 | |
586 | public function insertSelect( |
587 | $destTable, $srcTable, $varMap, $conds, |
588 | $fname = __METHOD__, $insertOptions = [], $selectOptions = [], $selectJoinConds = [] |
589 | ) { |
590 | $this->assertRoleAllowsWrites(); |
591 | |
592 | return $this->__call( __FUNCTION__, func_get_args() ); |
593 | } |
594 | |
595 | public function unionSupportsOrderAndLimit() { |
596 | return $this->__call( __FUNCTION__, func_get_args() ); |
597 | } |
598 | |
599 | public function unionQueries( $sqls, $all, $options = [] ) { |
600 | return $this->__call( __FUNCTION__, func_get_args() ); |
601 | } |
602 | |
603 | public function conditional( $cond, $caseTrueExpression, $caseFalseExpression ) { |
604 | return $this->__call( __FUNCTION__, func_get_args() ); |
605 | } |
606 | |
607 | public function strreplace( $orig, $old, $new ) { |
608 | return $this->__call( __FUNCTION__, func_get_args() ); |
609 | } |
610 | |
611 | public function wasDeadlock() { |
612 | return $this->__call( __FUNCTION__, func_get_args() ); |
613 | } |
614 | |
615 | public function wasReadOnlyError() { |
616 | return $this->__call( __FUNCTION__, func_get_args() ); |
617 | } |
618 | |
619 | public function primaryPosWait( DBPrimaryPos $pos, $timeout ) { |
620 | return $this->__call( __FUNCTION__, func_get_args() ); |
621 | } |
622 | |
623 | public function getReplicaPos() { |
624 | return $this->__call( __FUNCTION__, func_get_args() ); |
625 | } |
626 | |
627 | public function getPrimaryPos() { |
628 | return $this->__call( __FUNCTION__, func_get_args() ); |
629 | } |
630 | |
631 | public function serverIsReadOnly() { |
632 | return $this->__call( __FUNCTION__, func_get_args() ); |
633 | } |
634 | |
635 | public function onTransactionResolution( callable $callback, $fname = __METHOD__ ) { |
636 | // DB_REPLICA role: caller might want to refresh cache after a REPEATABLE-READ snapshot |
637 | return $this->__call( __FUNCTION__, func_get_args() ); |
638 | } |
639 | |
640 | public function onTransactionCommitOrIdle( callable $callback, $fname = __METHOD__ ) { |
641 | // DB_REPLICA role: caller might want to refresh cache after a REPEATABLE-READ snapshot |
642 | return $this->__call( __FUNCTION__, func_get_args() ); |
643 | } |
644 | |
645 | public function onTransactionPreCommitOrIdle( callable $callback, $fname = __METHOD__ ) { |
646 | // DB_REPLICA role: caller might want to refresh cache after a cache mutex is released |
647 | return $this->__call( __FUNCTION__, func_get_args() ); |
648 | } |
649 | |
650 | public function onAtomicSectionCancel( callable $callback, $fname = __METHOD__ ) { |
651 | return $this->__call( __FUNCTION__, func_get_args() ); |
652 | } |
653 | |
654 | public function setTransactionListener( $name, callable $callback = null ) { |
655 | return $this->__call( __FUNCTION__, func_get_args() ); |
656 | } |
657 | |
658 | public function startAtomic( |
659 | $fname = __METHOD__, $cancelable = IDatabase::ATOMIC_NOT_CANCELABLE |
660 | ) { |
661 | // Don't call assertRoleAllowsWrites(); caller might want a REPEATABLE-READ snapshot |
662 | return $this->__call( __FUNCTION__, func_get_args() ); |
663 | } |
664 | |
665 | public function endAtomic( $fname = __METHOD__ ) { |
666 | // Don't call assertRoleAllowsWrites(); caller might want a REPEATABLE-READ snapshot |
667 | return $this->__call( __FUNCTION__, func_get_args() ); |
668 | } |
669 | |
670 | public function cancelAtomic( $fname = __METHOD__, AtomicSectionIdentifier $sectionId = null ) { |
671 | // Don't call assertRoleAllowsWrites(); caller might want a REPEATABLE-READ snapshot |
672 | return $this->__call( __FUNCTION__, func_get_args() ); |
673 | } |
674 | |
675 | public function doAtomicSection( |
676 | $fname, callable $callback, $cancelable = self::ATOMIC_NOT_CANCELABLE |
677 | ) { |
678 | // Don't call assertRoleAllowsWrites(); caller might want a REPEATABLE-READ snapshot |
679 | return $this->__call( __FUNCTION__, func_get_args() ); |
680 | } |
681 | |
682 | public function begin( $fname = __METHOD__, $mode = IDatabase::TRANSACTION_EXPLICIT ) { |
683 | return $this->__call( __FUNCTION__, func_get_args() ); |
684 | } |
685 | |
686 | public function commit( $fname = __METHOD__, $flush = self::FLUSHING_ONE ) { |
687 | return $this->__call( __FUNCTION__, func_get_args() ); |
688 | } |
689 | |
690 | public function rollback( $fname = __METHOD__, $flush = self::FLUSHING_ONE ) { |
691 | return $this->__call( __FUNCTION__, func_get_args() ); |
692 | } |
693 | |
694 | public function flushSession( $fname = __METHOD__, $flush = self::FLUSHING_ONE ) { |
695 | return $this->__call( __FUNCTION__, func_get_args() ); |
696 | } |
697 | |
698 | public function flushSnapshot( $fname = __METHOD__, $flush = self::FLUSHING_ONE ) { |
699 | return $this->__call( __FUNCTION__, func_get_args() ); |
700 | } |
701 | |
702 | public function timestamp( $ts = 0 ) { |
703 | return $this->__call( __FUNCTION__, func_get_args() ); |
704 | } |
705 | |
706 | public function timestampOrNull( $ts = null ) { |
707 | return $this->__call( __FUNCTION__, func_get_args() ); |
708 | } |
709 | |
710 | public function ping( &$rtt = null ) { |
711 | return func_num_args() |
712 | ? $this->__call( __FUNCTION__, [ &$rtt ] ) |
713 | : $this->__call( __FUNCTION__, [] ); // method cares about null vs missing |
714 | } |
715 | |
716 | public function getLag() { |
717 | return $this->__call( __FUNCTION__, func_get_args() ); |
718 | } |
719 | |
720 | public function getSessionLagStatus() { |
721 | return $this->__call( __FUNCTION__, func_get_args() ); |
722 | } |
723 | |
724 | public function encodeBlob( $b ) { |
725 | return $this->__call( __FUNCTION__, func_get_args() ); |
726 | } |
727 | |
728 | public function decodeBlob( $b ) { |
729 | return $this->__call( __FUNCTION__, func_get_args() ); |
730 | } |
731 | |
732 | public function setSessionOptions( array $options ) { |
733 | $this->__call( __FUNCTION__, func_get_args() ); |
734 | } |
735 | |
736 | public function setSchemaVars( $vars ) { |
737 | return $this->__call( __FUNCTION__, func_get_args() ); |
738 | } |
739 | |
740 | public function lockIsFree( $lockName, $method ) { |
741 | $this->assertRoleAllowsWrites(); |
742 | |
743 | return $this->__call( __FUNCTION__, func_get_args() ); |
744 | } |
745 | |
746 | public function lock( $lockName, $method, $timeout = 5, $flags = 0 ) { |
747 | $this->assertRoleAllowsWrites(); |
748 | |
749 | return $this->__call( __FUNCTION__, func_get_args() ); |
750 | } |
751 | |
752 | public function unlock( $lockName, $method ) { |
753 | $this->assertRoleAllowsWrites(); |
754 | |
755 | return $this->__call( __FUNCTION__, func_get_args() ); |
756 | } |
757 | |
758 | public function getScopedLockAndFlush( $lockKey, $fname, $timeout ) { |
759 | $this->assertRoleAllowsWrites(); |
760 | |
761 | return $this->__call( __FUNCTION__, func_get_args() ); |
762 | } |
763 | |
764 | public function namedLocksEnqueue() { |
765 | return $this->__call( __FUNCTION__, func_get_args() ); |
766 | } |
767 | |
768 | public function getInfinity() { |
769 | return $this->__call( __FUNCTION__, func_get_args() ); |
770 | } |
771 | |
772 | public function encodeExpiry( $expiry ) { |
773 | return $this->__call( __FUNCTION__, func_get_args() ); |
774 | } |
775 | |
776 | public function decodeExpiry( $expiry, $format = TS_MW ) { |
777 | return $this->__call( __FUNCTION__, func_get_args() ); |
778 | } |
779 | |
780 | public function isReadOnly() { |
781 | return $this->__call( __FUNCTION__, func_get_args() ); |
782 | } |
783 | |
784 | public function setTableAliases( array $aliases ) { |
785 | return $this->__call( __FUNCTION__, func_get_args() ); |
786 | } |
787 | |
788 | public function getTableAliases() { |
789 | return $this->__call( __FUNCTION__, func_get_args() ); |
790 | } |
791 | |
792 | public function setIndexAliases( array $aliases ) { |
793 | return $this->__call( __FUNCTION__, func_get_args() ); |
794 | } |
795 | |
796 | public function tableName( $name, $format = 'quoted' ) { |
797 | return $this->__call( __FUNCTION__, func_get_args() ); |
798 | } |
799 | |
800 | public function tableNames( ...$tables ) { |
801 | return $this->__call( __FUNCTION__, func_get_args() ); |
802 | } |
803 | |
804 | public function tableNamesN( ...$tables ) { |
805 | return $this->__call( __FUNCTION__, func_get_args() ); |
806 | } |
807 | |
808 | public function sourceFile( |
809 | $filename, |
810 | callable $lineCallback = null, |
811 | callable $resultCallback = null, |
812 | $fname = false, |
813 | callable $inputCallback = null |
814 | ) { |
815 | $this->assertRoleAllowsWrites(); |
816 | |
817 | return $this->__call( __FUNCTION__, func_get_args() ); |
818 | } |
819 | |
820 | public function sourceStream( |
821 | $fp, |
822 | callable $lineCallback = null, |
823 | callable $resultCallback = null, |
824 | $fname = __METHOD__, |
825 | callable $inputCallback = null |
826 | ) { |
827 | $this->assertRoleAllowsWrites(); |
828 | |
829 | return $this->__call( __FUNCTION__, func_get_args() ); |
830 | } |
831 | |
832 | public function dropTable( $table, $fname = __METHOD__ ) { |
833 | $this->assertRoleAllowsWrites(); |
834 | |
835 | return $this->__call( __FUNCTION__, func_get_args() ); |
836 | } |
837 | |
838 | public function truncateTable( $table, $fname = __METHOD__ ) { |
839 | $this->assertRoleAllowsWrites(); |
840 | |
841 | return $this->__call( __FUNCTION__, func_get_args() ); |
842 | } |
843 | |
844 | public function truncate( $tables, $fname = __METHOD__ ) { |
845 | $this->assertRoleAllowsWrites(); |
846 | |
847 | return $this->__call( __FUNCTION__, func_get_args() ); |
848 | } |
849 | |
850 | public function listViews( $prefix = null, $fname = __METHOD__ ) { |
851 | return $this->__call( __FUNCTION__, func_get_args() ); |
852 | } |
853 | |
854 | public function textFieldSize( $table, $field ) { |
855 | return $this->__call( __FUNCTION__, func_get_args() ); |
856 | } |
857 | |
858 | public function streamStatementEnd( &$sql, &$newLine ) { |
859 | return $this->__call( __FUNCTION__, [ &$sql, &$newLine ] ); |
860 | } |
861 | |
862 | public function duplicateTableStructure( |
863 | $oldName, $newName, $temporary = false, $fname = __METHOD__ |
864 | ) { |
865 | $this->assertRoleAllowsWrites(); |
866 | |
867 | return $this->__call( __FUNCTION__, func_get_args() ); |
868 | } |
869 | |
870 | public function indexUnique( $table, $index, $fname = __METHOD__ ) { |
871 | return $this->__call( __FUNCTION__, func_get_args() ); |
872 | } |
873 | |
874 | public function listTables( $prefix = null, $fname = __METHOD__ ) { |
875 | return $this->__call( __FUNCTION__, func_get_args() ); |
876 | } |
877 | |
878 | public function fieldInfo( $table, $field ) { |
879 | return $this->__call( __FUNCTION__, func_get_args() ); |
880 | } |
881 | |
882 | public function __toString() { |
883 | if ( $this->conn === null ) { |
884 | return $this->getType() . ' object #' . spl_object_id( $this ); |
885 | } |
886 | |
887 | return $this->__call( __FUNCTION__, func_get_args() ); |
888 | } |
889 | |
890 | /** |
891 | * Error out if the role is not DB_PRIMARY |
892 | * |
893 | * Note that the underlying connection may or may not itself be read-only. |
894 | * It could even be to a writable primary (both server-side and to the application). |
895 | * This error is meant for the case when a DB_REPLICA handle was requested but a |
896 | * a write was attempted on that handle regardless. |
897 | * |
898 | * In configurations where the primary DB has some generic read load or is the only server, |
899 | * DB_PRIMARY/DB_REPLICA will sometimes (or always) use the same connection to the primary DB. |
900 | * This does not effect the role of DBConnRef instances. |
901 | * @throws DBReadOnlyRoleError |
902 | */ |
903 | protected function assertRoleAllowsWrites() { |
904 | // DB_PRIMARY is "prima facie" writable |
905 | if ( $this->role !== ILoadBalancer::DB_PRIMARY ) { |
906 | throw new DBReadOnlyRoleError( $this->conn, "Cannot write with role DB_REPLICA" ); |
907 | } |
908 | } |
909 | |
910 | /** |
911 | * @return DBUnexpectedError |
912 | */ |
913 | protected function getDomainChangeException() { |
914 | return new DBUnexpectedError( |
915 | $this, |
916 | "Cannot directly change the selected DB domain; any underlying connection handle " . |
917 | "is owned by a LoadBalancer instance and possibly shared with other callers. " . |
918 | "LoadBalancer automatically manages DB domain re-selection of unused handles." |
919 | ); |
920 | } |
921 | |
922 | /** |
923 | * @param int $i Specific or virtual (DB_PRIMARY/DB_REPLICA) server index |
924 | * @return int|mixed |
925 | */ |
926 | protected function normalizeServerIndex( $i ) { |
927 | return ( $i === ILoadBalancer::DB_PRIMARY ) ? $this->lb->getWriterIndex() : $i; |
928 | } |
929 | } |