The Database class was previously just a short-hand for "Database::", and such calls should still work. The class now resides in /libs/rdbms. The subclasses now extend DatabaseBase to avoid breaking type hints that use that (hints use either IDatabase or DatabaseBase). Also, use CASCADE with DROP TABLE for MySQL as with other DBs. Keep SQLite excempt due to lack of support. Added getDomainID() methods to avoid mentioning the word "wiki". Change-Id: Ibd05d786cb26c21dcc9cb9601f6b2b52056af9ae
225 lines
5.6 KiB
PHP
225 lines
5.6 KiB
PHP
<?php
|
|
/**
|
|
* @defgroup Database Database
|
|
*
|
|
* This file deals with database interface functions
|
|
* and query specifics/optimisations.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*
|
|
* @file
|
|
* @ingroup Database
|
|
*/
|
|
|
|
/**
|
|
* Database abstraction object
|
|
* @ingroup Database
|
|
*/
|
|
abstract class DatabaseBase extends Database {
|
|
/**
|
|
* Boolean, controls output of large amounts of debug information.
|
|
* @param bool|null $debug
|
|
* - true to enable debugging
|
|
* - false to disable debugging
|
|
* - omitted or null to do nothing
|
|
*
|
|
* @return bool Previous value of the flag
|
|
* @deprecated since 1.28; use setFlag()
|
|
*/
|
|
public function debug( $debug = null ) {
|
|
$res = $this->getFlag( DBO_DEBUG );
|
|
if ( $debug !== null ) {
|
|
$debug ? $this->setFlag( DBO_DEBUG ) : $this->clearFlag( DBO_DEBUG );
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* @return string Command delimiter used by this database engine
|
|
*/
|
|
public function getDelimiter() {
|
|
return $this->delimiter;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this database supports (and uses) cascading deletes
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function cascadingDeletes() {
|
|
return false;
|
|
}
|
|
/**
|
|
* Returns true if this database supports (and uses) triggers (e.g. on the page table)
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function cleanupTriggers() {
|
|
return false;
|
|
}
|
|
/**
|
|
* Returns true if this database is strict about what can be put into an IP field.
|
|
* Specifically, it uses a NULL value instead of an empty string.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function strictIPs() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this database can do a native search on IP columns
|
|
* e.g. this works as expected: .. WHERE rc_ip = '127.42.12.102/32';
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function searchableIPs() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this database uses timestamps rather than integers
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function realTimestamps() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this database can use functional indexes
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function functionalIndexes() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Intended to be compatible with the PEAR::DB wrapper functions.
|
|
* http://pear.php.net/manual/en/package.database.db.intro-execute.php
|
|
*
|
|
* ? = scalar value, quoted as necessary
|
|
* ! = raw SQL bit (a function for instance)
|
|
* & = filename; reads the file and inserts as a blob
|
|
* (we don't use this though...)
|
|
*
|
|
* @param string $sql
|
|
* @param string $func
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function prepare( $sql, $func = __METHOD__ ) {
|
|
/* MySQL doesn't support prepared statements (yet), so just
|
|
* pack up the query for reference. We'll manually replace
|
|
* the bits later.
|
|
*/
|
|
return [ 'query' => $sql, 'func' => $func ];
|
|
}
|
|
|
|
/**
|
|
* Free a prepared query, generated by prepare().
|
|
* @param string $prepared
|
|
*/
|
|
protected function freePrepared( $prepared ) {
|
|
/* No-op by default */
|
|
}
|
|
|
|
/**
|
|
* Execute a prepared query with the various arguments
|
|
* @param string $prepared The prepared sql
|
|
* @param mixed $args Either an array here, or put scalars as varargs
|
|
*
|
|
* @return ResultWrapper
|
|
*/
|
|
public function execute( $prepared, $args = null ) {
|
|
if ( !is_array( $args ) ) {
|
|
# Pull the var args
|
|
$args = func_get_args();
|
|
array_shift( $args );
|
|
}
|
|
|
|
$sql = $this->fillPrepared( $prepared['query'], $args );
|
|
|
|
return $this->query( $sql, $prepared['func'] );
|
|
}
|
|
|
|
/**
|
|
* For faking prepared SQL statements on DBs that don't support it directly.
|
|
*
|
|
* @param string $preparedQuery A 'preparable' SQL statement
|
|
* @param array $args Array of Arguments to fill it with
|
|
* @return string Executable SQL
|
|
*/
|
|
public function fillPrepared( $preparedQuery, $args ) {
|
|
reset( $args );
|
|
$this->preparedArgs =& $args;
|
|
|
|
return preg_replace_callback( '/(\\\\[?!&]|[?!&])/',
|
|
[ &$this, 'fillPreparedArg' ], $preparedQuery );
|
|
}
|
|
|
|
/**
|
|
* preg_callback func for fillPrepared()
|
|
* The arguments should be in $this->preparedArgs and must not be touched
|
|
* while we're doing this.
|
|
*
|
|
* @param array $matches
|
|
* @throws DBUnexpectedError
|
|
* @return string
|
|
*/
|
|
protected function fillPreparedArg( $matches ) {
|
|
switch ( $matches[1] ) {
|
|
case '\\?':
|
|
return '?';
|
|
case '\\!':
|
|
return '!';
|
|
case '\\&':
|
|
return '&';
|
|
}
|
|
|
|
list( /* $n */, $arg ) = each( $this->preparedArgs );
|
|
|
|
switch ( $matches[1] ) {
|
|
case '?':
|
|
return $this->addQuotes( $arg );
|
|
case '!':
|
|
return $arg;
|
|
case '&':
|
|
# return $this->addQuotes( file_get_contents( $arg ) );
|
|
throw new DBUnexpectedError(
|
|
$this,
|
|
'& mode is not implemented. If it\'s really needed, uncomment the line above.'
|
|
);
|
|
default:
|
|
throw new DBUnexpectedError(
|
|
$this,
|
|
'Received invalid match. This should never happen!'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get search engine class. All subclasses of this need to implement this
|
|
* if they wish to use searching.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getSearchEngine() {
|
|
return 'SearchEngineDummy';
|
|
}
|
|
}
|