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 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.
);
}
- public function testFillPreparedEmpty() {
- $sql = $this->db->fillPrepared(
- 'SELECT * FROM interwiki', [] );
- $this->assertEquals(
- "SELECT * FROM interwiki",
- $sql );
- }
-
- public function testFillPreparedQuestion() {
- $sql = $this->db->fillPrepared(
- 'SELECT * FROM cur WHERE cur_namespace=? AND cur_title=?',
- [ 4, "Snicker's_paradox" ] );
-
- $check = "SELECT * FROM cur WHERE cur_namespace='4' AND cur_title='Snicker''s_paradox'";
- if ( $this->db->getType() === 'mysql' ) {
- $check = "SELECT * FROM cur WHERE cur_namespace='4' AND cur_title='Snicker\'s_paradox'";
- }
- $this->assertEquals( $check, $sql );
- }
-
- public function testFillPreparedBang() {
- $sql = $this->db->fillPrepared(
- 'SELECT user_id FROM ! WHERE user_name=?',
- [ '"user"', "Slash's Dot" ] );
-
- $check = "SELECT user_id FROM \"user\" WHERE user_name='Slash''s Dot'";
- if ( $this->db->getType() === 'mysql' ) {
- $check = "SELECT user_id FROM \"user\" WHERE user_name='Slash\'s Dot'";
- }
- $this->assertEquals( $check, $sql );
- }
-
- public function testFillPreparedRaw() {
- $sql = $this->db->fillPrepared(
- "SELECT * FROM cur WHERE cur_title='This_\\&_that,_WTF\\?\\!'",
- [ '"user"', "Slash's Dot" ] );
- $this->assertEquals(
- "SELECT * FROM cur WHERE cur_title='This_&_that,_WTF?!'",
- $sql );
- }
-
public function testStoredFunctions() {
if ( !in_array( wfGetDB( DB_MASTER )->getType(), [ 'mysql', 'postgres' ] ) ) {
$this->markTestSkipped( 'MySQL or Postgres required' );