mirror of
https://we.phorge.it/source/phorge.git
synced 2025-03-28 12:08:14 +01:00
Remove AphrontConnection from Phabricator
Summary: See D3055. Test Plan: Loaded pages and such. Reviewers: vrana, btrahan Reviewed By: vrana CC: aran Maniphest Tasks: T1283 Differential Revision: https://secure.phabricator.com/D3056
This commit is contained in:
parent
27f6cc3b27
commit
17e20bc363
19 changed files with 0 additions and 1207 deletions
|
@ -23,8 +23,6 @@ phutil_register_library_map(array(
|
|||
'AphrontContextBarView' => 'view/layout/AphrontContextBarView.php',
|
||||
'AphrontController' => 'aphront/AphrontController.php',
|
||||
'AphrontCrumbsView' => 'view/layout/AphrontCrumbsView.php',
|
||||
'AphrontDatabaseConnection' => 'infrastructure/storage/connection/AphrontDatabaseConnection.php',
|
||||
'AphrontDatabaseTransactionState' => 'infrastructure/storage/connection/AphrontDatabaseTransactionState.php',
|
||||
'AphrontDefaultApplicationConfiguration' => 'aphront/configuration/AphrontDefaultApplicationConfiguration.php',
|
||||
'AphrontDialogResponse' => 'aphront/response/AphrontDialogResponse.php',
|
||||
'AphrontDialogView' => 'view/AphrontDialogView.php',
|
||||
|
@ -60,7 +58,6 @@ phutil_register_library_map(array(
|
|||
'AphrontHeadsupActionView' => 'view/layout/headsup/AphrontHeadsupActionView.php',
|
||||
'AphrontHeadsupView' => 'view/layout/headsup/AphrontHeadsupView.php',
|
||||
'AphrontIDPagerView' => 'view/control/AphrontIDPagerView.php',
|
||||
'AphrontIsolatedDatabaseConnection' => 'infrastructure/storage/connection/AphrontIsolatedDatabaseConnection.php',
|
||||
'AphrontIsolatedDatabaseConnectionTestCase' => 'infrastructure/storage/connection/__tests__/AphrontIsolatedDatabaseConnectionTestCase.php',
|
||||
'AphrontIsolatedHTTPSink' => 'aphront/sink/AphrontIsolatedHTTPSink.php',
|
||||
'AphrontJSONResponse' => 'aphront/response/AphrontJSONResponse.php',
|
||||
|
@ -69,10 +66,7 @@ phutil_register_library_map(array(
|
|||
'AphrontListFilterView' => 'view/layout/AphrontListFilterView.php',
|
||||
'AphrontMiniPanelView' => 'view/layout/AphrontMiniPanelView.php',
|
||||
'AphrontMoreView' => 'view/layout/AphrontMoreView.php',
|
||||
'AphrontMySQLDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php',
|
||||
'AphrontMySQLDatabaseConnectionBase' => 'infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnectionBase.php',
|
||||
'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/connection/__tests__/AphrontMySQLDatabaseConnectionTestCase.php',
|
||||
'AphrontMySQLiDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php',
|
||||
'AphrontNullView' => 'view/AphrontNullView.php',
|
||||
'AphrontPHPHTTPSink' => 'aphront/sink/AphrontPHPHTTPSink.php',
|
||||
'AphrontPageView' => 'view/page/AphrontPageView.php',
|
||||
|
@ -80,18 +74,6 @@ phutil_register_library_map(array(
|
|||
'AphrontPanelView' => 'view/layout/AphrontPanelView.php',
|
||||
'AphrontPlainTextResponse' => 'aphront/response/AphrontPlainTextResponse.php',
|
||||
'AphrontProxyResponse' => 'aphront/response/AphrontProxyResponse.php',
|
||||
'AphrontQueryAccessDeniedException' => 'infrastructure/storage/exception/AphrontQueryAccessDeniedException.php',
|
||||
'AphrontQueryConnectionException' => 'infrastructure/storage/exception/AphrontQueryConnectionException.php',
|
||||
'AphrontQueryConnectionLostException' => 'infrastructure/storage/exception/AphrontQueryConnectionLostException.php',
|
||||
'AphrontQueryCountException' => 'infrastructure/storage/exception/AphrontQueryCountException.php',
|
||||
'AphrontQueryDeadlockException' => 'infrastructure/storage/exception/AphrontQueryDeadlockException.php',
|
||||
'AphrontQueryDuplicateKeyException' => 'infrastructure/storage/exception/AphrontQueryDuplicateKeyException.php',
|
||||
'AphrontQueryException' => 'infrastructure/storage/exception/AphrontQueryException.php',
|
||||
'AphrontQueryNotSupportedException' => 'infrastructure/storage/exception/AphrontQueryNotSupportedException.php',
|
||||
'AphrontQueryObjectMissingException' => 'infrastructure/storage/exception/AphrontQueryObjectMissingException.php',
|
||||
'AphrontQueryParameterException' => 'infrastructure/storage/exception/AphrontQueryParameterException.php',
|
||||
'AphrontQueryRecoverableException' => 'infrastructure/storage/exception/AphrontQueryRecoverableException.php',
|
||||
'AphrontQuerySchemaException' => 'infrastructure/storage/exception/AphrontQuerySchemaException.php',
|
||||
'AphrontRedirectException' => 'aphront/exception/AphrontRedirectException.php',
|
||||
'AphrontRedirectResponse' => 'aphront/response/AphrontRedirectResponse.php',
|
||||
'AphrontReloadResponse' => 'aphront/response/AphrontReloadResponse.php',
|
||||
|
@ -1179,7 +1161,6 @@ phutil_register_library_map(array(
|
|||
'AphrontHeadsupActionView' => 'AphrontView',
|
||||
'AphrontHeadsupView' => 'AphrontView',
|
||||
'AphrontIDPagerView' => 'AphrontView',
|
||||
'AphrontIsolatedDatabaseConnection' => 'AphrontDatabaseConnection',
|
||||
'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase',
|
||||
'AphrontIsolatedHTTPSink' => 'AphrontHTTPSink',
|
||||
'AphrontJSONResponse' => 'AphrontResponse',
|
||||
|
@ -1188,10 +1169,7 @@ phutil_register_library_map(array(
|
|||
'AphrontListFilterView' => 'AphrontView',
|
||||
'AphrontMiniPanelView' => 'AphrontView',
|
||||
'AphrontMoreView' => 'AphrontView',
|
||||
'AphrontMySQLDatabaseConnection' => 'AphrontMySQLDatabaseConnectionBase',
|
||||
'AphrontMySQLDatabaseConnectionBase' => 'AphrontDatabaseConnection',
|
||||
'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase',
|
||||
'AphrontMySQLiDatabaseConnection' => 'AphrontMySQLDatabaseConnectionBase',
|
||||
'AphrontNullView' => 'AphrontView',
|
||||
'AphrontPHPHTTPSink' => 'AphrontHTTPSink',
|
||||
'AphrontPageView' => 'AphrontView',
|
||||
|
@ -1199,18 +1177,6 @@ phutil_register_library_map(array(
|
|||
'AphrontPanelView' => 'AphrontView',
|
||||
'AphrontPlainTextResponse' => 'AphrontResponse',
|
||||
'AphrontProxyResponse' => 'AphrontResponse',
|
||||
'AphrontQueryAccessDeniedException' => 'AphrontQueryRecoverableException',
|
||||
'AphrontQueryConnectionException' => 'AphrontQueryException',
|
||||
'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException',
|
||||
'AphrontQueryCountException' => 'AphrontQueryException',
|
||||
'AphrontQueryDeadlockException' => 'AphrontQueryRecoverableException',
|
||||
'AphrontQueryDuplicateKeyException' => 'AphrontQueryException',
|
||||
'AphrontQueryException' => 'Exception',
|
||||
'AphrontQueryNotSupportedException' => 'AphrontQueryException',
|
||||
'AphrontQueryObjectMissingException' => 'AphrontQueryException',
|
||||
'AphrontQueryParameterException' => 'AphrontQueryException',
|
||||
'AphrontQueryRecoverableException' => 'AphrontQueryException',
|
||||
'AphrontQuerySchemaException' => 'AphrontQueryException',
|
||||
'AphrontRedirectException' => 'AphrontException',
|
||||
'AphrontRedirectResponse' => 'AphrontResponse',
|
||||
'AphrontReloadResponse' => 'AphrontRedirectResponse',
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @task xaction Transaction Management
|
||||
* @group storage
|
||||
*/
|
||||
abstract class AphrontDatabaseConnection {
|
||||
|
||||
private $transactionState;
|
||||
|
||||
abstract public function getInsertID();
|
||||
abstract public function getAffectedRows();
|
||||
abstract public function selectAllResults();
|
||||
abstract public function executeRawQuery($raw_query);
|
||||
abstract public function close();
|
||||
|
||||
abstract public function escapeString($string);
|
||||
abstract public function escapeColumnName($string);
|
||||
abstract public function escapeMultilineComment($string);
|
||||
abstract public function escapeStringForLikeClause($string);
|
||||
|
||||
public function queryData($pattern/* , $arg, $arg, ... */) {
|
||||
$args = func_get_args();
|
||||
array_unshift($args, $this);
|
||||
return call_user_func_array('queryfx_all', $args);
|
||||
}
|
||||
|
||||
public function query($pattern/* , $arg, $arg, ... */) {
|
||||
$args = func_get_args();
|
||||
array_unshift($args, $this);
|
||||
return call_user_func_array('queryfx', $args);
|
||||
}
|
||||
|
||||
|
||||
/* -( Transaction Management )--------------------------------------------- */
|
||||
|
||||
|
||||
/**
|
||||
* Begin a transaction, or set a savepoint if the connection is already
|
||||
* transactional.
|
||||
*
|
||||
* @return this
|
||||
* @task xaction
|
||||
*/
|
||||
public function openTransaction() {
|
||||
$state = $this->getTransactionState();
|
||||
$point = $state->getSavepointName();
|
||||
$depth = $state->increaseDepth();
|
||||
|
||||
$new_transaction = ($depth == 1);
|
||||
if ($new_transaction) {
|
||||
$this->query('START TRANSACTION');
|
||||
} else {
|
||||
$this->query('SAVEPOINT '.$point);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commit a transaction, or stage a savepoint for commit once the entire
|
||||
* transaction completes if inside a transaction stack.
|
||||
*
|
||||
* @return this
|
||||
* @task xaction
|
||||
*/
|
||||
public function saveTransaction() {
|
||||
$state = $this->getTransactionState();
|
||||
$depth = $state->decreaseDepth();
|
||||
|
||||
if ($depth == 0) {
|
||||
$this->query('COMMIT');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rollback a transaction, or unstage the last savepoint if inside a
|
||||
* transaction stack.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
public function killTransaction() {
|
||||
$state = $this->getTransactionState();
|
||||
$depth = $state->decreaseDepth();
|
||||
|
||||
if ($depth == 0) {
|
||||
$this->query('ROLLBACK');
|
||||
} else {
|
||||
$this->query('ROLLBACK TO SAVEPOINT '.$state->getSavepointName());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the connection is transactional.
|
||||
*
|
||||
* @return bool True if the connection is currently transactional.
|
||||
* @task xaction
|
||||
*/
|
||||
public function isInsideTransaction() {
|
||||
$state = $this->getTransactionState();
|
||||
return ($state->getDepth() > 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current @{class:AphrontDatabaseTransactionState} object, or create
|
||||
* one if none exists.
|
||||
*
|
||||
* @return AphrontDatabaseTransactionState Current transaction state.
|
||||
* @task xaction
|
||||
*/
|
||||
protected function getTransactionState() {
|
||||
if (!$this->transactionState) {
|
||||
$this->transactionState = new AphrontDatabaseTransactionState();
|
||||
}
|
||||
return $this->transactionState;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task xaction
|
||||
*/
|
||||
public function beginReadLocking() {
|
||||
$this->getTransactionState()->beginReadLocking();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task xaction
|
||||
*/
|
||||
public function endReadLocking() {
|
||||
$this->getTransactionState()->endReadLocking();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task xaction
|
||||
*/
|
||||
public function isReadLocking() {
|
||||
return $this->getTransactionState()->isReadLocking();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task xaction
|
||||
*/
|
||||
public function beginWriteLocking() {
|
||||
$this->getTransactionState()->beginWriteLocking();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task xaction
|
||||
*/
|
||||
public function endWriteLocking() {
|
||||
$this->getTransactionState()->endWriteLocking();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task xaction
|
||||
*/
|
||||
public function isWriteLocking() {
|
||||
return $this->getTransactionState()->isWriteLocking();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents current transaction state of a connection.
|
||||
*
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontDatabaseTransactionState {
|
||||
|
||||
private $depth = 0;
|
||||
private $readLockLevel = 0;
|
||||
private $writeLockLevel = 0;
|
||||
|
||||
public function getDepth() {
|
||||
return $this->depth;
|
||||
}
|
||||
|
||||
public function increaseDepth() {
|
||||
return ++$this->depth;
|
||||
}
|
||||
|
||||
public function decreaseDepth() {
|
||||
if ($this->depth == 0) {
|
||||
throw new Exception(
|
||||
'Too many calls to saveTransaction() or killTransaction()!');
|
||||
}
|
||||
|
||||
return --$this->depth;
|
||||
}
|
||||
|
||||
public function getSavepointName() {
|
||||
return 'Aphront_Savepoint_'.$this->depth;
|
||||
}
|
||||
|
||||
public function beginReadLocking() {
|
||||
$this->readLockLevel++;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function endReadLocking() {
|
||||
if ($this->readLockLevel == 0) {
|
||||
throw new Exception("Too many calls to endReadLocking()!");
|
||||
}
|
||||
$this->readLockLevel--;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isReadLocking() {
|
||||
return ($this->readLockLevel > 0);
|
||||
}
|
||||
|
||||
public function beginWriteLocking() {
|
||||
$this->writeLockLevel++;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function endWriteLocking() {
|
||||
if ($this->writeLockLevel == 0) {
|
||||
throw new Exception("Too many calls to endWriteLocking()!");
|
||||
}
|
||||
$this->writeLockLevel--;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isWriteLocking() {
|
||||
return ($this->writeLockLevel > 0);
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
if ($this->depth) {
|
||||
throw new Exception(
|
||||
'Process exited with an open transaction! The transaction will be '.
|
||||
'implicitly rolled back. Calls to openTransaction() must always be '.
|
||||
'paired with a call to saveTransaction() or killTransaction().');
|
||||
}
|
||||
if ($this->readLockLevel) {
|
||||
throw new Exception(
|
||||
'Process exited with an open read lock! Call to beginReadLocking() '.
|
||||
'must always be paired with a call to endReadLocking().');
|
||||
}
|
||||
if ($this->writeLockLevel) {
|
||||
throw new Exception(
|
||||
'Process exited with an open write lock! Call to beginWriteLocking() '.
|
||||
'must always be paired with a call to endWriteLocking().');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontIsolatedDatabaseConnection
|
||||
extends AphrontDatabaseConnection {
|
||||
|
||||
private $configuration;
|
||||
private static $nextInsertID;
|
||||
private $insertID;
|
||||
|
||||
private $transcript = array();
|
||||
|
||||
public function __construct(array $configuration) {
|
||||
$this->configuration = $configuration;
|
||||
|
||||
if (self::$nextInsertID === null) {
|
||||
// Generate test IDs into a distant ID space to reduce the risk of
|
||||
// collisions and make them distinctive.
|
||||
self::$nextInsertID = 55555000000 + mt_rand(0, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public function close() {
|
||||
return;
|
||||
}
|
||||
|
||||
public function escapeString($string) {
|
||||
return '<S>';
|
||||
}
|
||||
|
||||
public function escapeColumnName($name) {
|
||||
return '<C>';
|
||||
}
|
||||
|
||||
public function escapeMultilineComment($comment) {
|
||||
return '<K>';
|
||||
}
|
||||
|
||||
public function escapeStringForLikeClause($value) {
|
||||
return '<L>';
|
||||
}
|
||||
|
||||
private function getConfiguration($key, $default = null) {
|
||||
return idx($this->configuration, $key, $default);
|
||||
}
|
||||
|
||||
public function getInsertID() {
|
||||
return $this->insertID;
|
||||
}
|
||||
|
||||
public function getAffectedRows() {
|
||||
return $this->affectedRows;
|
||||
}
|
||||
|
||||
public function selectAllResults() {
|
||||
return $this->allResults;
|
||||
}
|
||||
|
||||
public function executeRawQuery($raw_query) {
|
||||
|
||||
// NOTE: "[\s<>K]*" allows any number of (properly escaped) comments to
|
||||
// appear prior to the allowed keyword, since this connection escapes
|
||||
// them as "<K>" (above).
|
||||
|
||||
$keywords = array(
|
||||
'INSERT',
|
||||
'UPDATE',
|
||||
'DELETE',
|
||||
'START',
|
||||
'SAVEPOINT',
|
||||
'COMMIT',
|
||||
'ROLLBACK',
|
||||
);
|
||||
$preg_keywords = array();
|
||||
foreach ($keywords as $key => $word) {
|
||||
$preg_keywords[] = preg_quote($word, '/');
|
||||
}
|
||||
$preg_keywords = implode('|', $preg_keywords);
|
||||
|
||||
if (!preg_match('/^[\s<>K]*('.$preg_keywords.')\s*/i', $raw_query)) {
|
||||
throw new AphrontQueryNotSupportedException(
|
||||
"Database isolation currently only supports some queries. You are ".
|
||||
"trying to issue a query which does not begin with an allowed ".
|
||||
"keyword (".implode(', ', $keywords)."): '".$raw_query."'");
|
||||
}
|
||||
|
||||
$this->transcript[] = $raw_query;
|
||||
|
||||
// NOTE: This method is intentionally simplified for now, since we're only
|
||||
// using it to stub out inserts/updates. In the future it will probably need
|
||||
// to grow more powerful.
|
||||
|
||||
$this->allResults = array();
|
||||
|
||||
// NOTE: We jitter the insert IDs to keep tests honest; a test should cover
|
||||
// the relationship between objects, not their exact insertion order. This
|
||||
// guarantees that IDs are unique but makes it impossible to hard-code tests
|
||||
// against this specific implementation detail.
|
||||
self::$nextInsertID += mt_rand(1, 10);
|
||||
$this->insertID = self::$nextInsertID;
|
||||
$this->affectedRows = 1;
|
||||
}
|
||||
|
||||
public function getQueryTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontMySQLDatabaseConnection
|
||||
extends AphrontMySQLDatabaseConnectionBase {
|
||||
|
||||
public function escapeString($string) {
|
||||
return mysql_real_escape_string($string, $this->requireConnection());
|
||||
}
|
||||
|
||||
public function getInsertID() {
|
||||
return mysql_insert_id($this->requireConnection());
|
||||
}
|
||||
|
||||
public function getAffectedRows() {
|
||||
return mysql_affected_rows($this->requireConnection());
|
||||
}
|
||||
|
||||
protected function closeConnection() {
|
||||
mysql_close($this->requireConnection());
|
||||
}
|
||||
|
||||
protected function connect() {
|
||||
if (!function_exists('mysql_connect')) {
|
||||
// We have to '@' the actual call since it can spew all sorts of silly
|
||||
// noise, but it will also silence fatals caused by not having MySQL
|
||||
// installed, which has bitten me on three separate occasions. Make sure
|
||||
// such failures are explicit and loud.
|
||||
throw new Exception(
|
||||
"About to call mysql_connect(), but the PHP MySQL extension is not ".
|
||||
"available!");
|
||||
}
|
||||
|
||||
$user = $this->getConfiguration('user');
|
||||
$host = $this->getConfiguration('host');
|
||||
$database = $this->getConfiguration('database');
|
||||
|
||||
$pass = $this->getConfiguration('pass');
|
||||
if ($pass instanceof PhutilOpaqueEnvelope) {
|
||||
$pass = $pass->openEnvelope();
|
||||
}
|
||||
|
||||
$conn = @mysql_connect(
|
||||
$host,
|
||||
$user,
|
||||
$pass,
|
||||
$new_link = true,
|
||||
$flags = 0);
|
||||
|
||||
if (!$conn) {
|
||||
$errno = mysql_errno();
|
||||
$error = mysql_error();
|
||||
throw new AphrontQueryConnectionException(
|
||||
"Attempt to connect to {$user}@{$host} failed with error ".
|
||||
"#{$errno}: {$error}.", $errno);
|
||||
}
|
||||
|
||||
if ($database !== null) {
|
||||
$ret = @mysql_select_db($database, $conn);
|
||||
if (!$ret) {
|
||||
$this->throwQueryException($conn);
|
||||
}
|
||||
}
|
||||
|
||||
mysql_set_charset('utf8', $conn);
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
protected function rawQuery($raw_query) {
|
||||
return @mysql_query($raw_query, $this->requireConnection());
|
||||
}
|
||||
|
||||
protected function fetchAssoc($result) {
|
||||
return mysql_fetch_assoc($result);
|
||||
}
|
||||
|
||||
protected function getErrorCode($connection) {
|
||||
return mysql_errno($connection);
|
||||
}
|
||||
|
||||
protected function getErrorDescription($connection) {
|
||||
return mysql_error($connection);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,261 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
abstract class AphrontMySQLDatabaseConnectionBase
|
||||
extends AphrontDatabaseConnection {
|
||||
|
||||
private $configuration;
|
||||
private $connection;
|
||||
|
||||
private $nextError;
|
||||
|
||||
abstract protected function connect();
|
||||
abstract protected function rawQuery($raw_query);
|
||||
abstract protected function fetchAssoc($result);
|
||||
abstract protected function getErrorCode($connection);
|
||||
abstract protected function getErrorDescription($connection);
|
||||
abstract protected function closeConnection();
|
||||
|
||||
public function __construct(array $configuration) {
|
||||
$this->configuration = $configuration;
|
||||
}
|
||||
|
||||
public function close() {
|
||||
if ($this->connection) {
|
||||
$this->closeConnection();
|
||||
$this->connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
public function escapeColumnName($name) {
|
||||
return '`'.str_replace('`', '``', $name).'`';
|
||||
}
|
||||
|
||||
|
||||
public function escapeMultilineComment($comment) {
|
||||
// These can either terminate a comment, confuse the hell out of the parser,
|
||||
// make MySQL execute the comment as a query, or, in the case of semicolon,
|
||||
// are quasi-dangerous because the semicolon could turn a broken query into
|
||||
// a working query plus an ignored query.
|
||||
|
||||
static $map = array(
|
||||
'--' => '(DOUBLEDASH)',
|
||||
'*/' => '(STARSLASH)',
|
||||
'//' => '(SLASHSLASH)',
|
||||
'#' => '(HASH)',
|
||||
'!' => '(BANG)',
|
||||
';' => '(SEMICOLON)',
|
||||
);
|
||||
|
||||
$comment = str_replace(
|
||||
array_keys($map),
|
||||
array_values($map),
|
||||
$comment);
|
||||
|
||||
// For good measure, kill anything else that isn't a nice printable
|
||||
// character.
|
||||
$comment = preg_replace('/[^\x20-\x7F]+/', ' ', $comment);
|
||||
|
||||
return '/* '.$comment.' */';
|
||||
}
|
||||
|
||||
public function escapeStringForLikeClause($value) {
|
||||
$value = addcslashes($value, '\%_');
|
||||
$value = $this->escapeString($value);
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function getConfiguration($key, $default = null) {
|
||||
return idx($this->configuration, $key, $default);
|
||||
}
|
||||
|
||||
private function establishConnection() {
|
||||
$start = microtime(true);
|
||||
|
||||
$host = $this->getConfiguration('host');
|
||||
$database = $this->getConfiguration('database');
|
||||
|
||||
$profiler = PhutilServiceProfiler::getInstance();
|
||||
$call_id = $profiler->beginServiceCall(
|
||||
array(
|
||||
'type' => 'connect',
|
||||
'host' => $host,
|
||||
'database' => $database,
|
||||
));
|
||||
|
||||
$retries = max(1, $this->getConfiguration('retries', 3));
|
||||
while ($retries--) {
|
||||
try {
|
||||
$conn = $this->connect();
|
||||
$profiler->endServiceCall($call_id, array());
|
||||
break;
|
||||
} catch (AphrontQueryException $ex) {
|
||||
if ($retries && $ex->getCode() == 2003) {
|
||||
$class = get_class($ex);
|
||||
$message = $ex->getMessage();
|
||||
phlog("Retrying ({$retries}) after {$class}: {$message}");
|
||||
} else {
|
||||
$profiler->endServiceCall($call_id, array());
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->connection = $conn;
|
||||
}
|
||||
|
||||
protected function requireConnection() {
|
||||
if (!$this->connection) {
|
||||
$this->establishConnection();
|
||||
}
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
public function selectAllResults() {
|
||||
$result = array();
|
||||
$res = $this->lastResult;
|
||||
if ($res == null) {
|
||||
throw new Exception('No query result to fetch from!');
|
||||
}
|
||||
while (($row = $this->fetchAssoc($res))) {
|
||||
$result[] = $row;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function executeRawQuery($raw_query) {
|
||||
$this->lastResult = null;
|
||||
$retries = max(1, $this->getConfiguration('retries', 3));
|
||||
while ($retries--) {
|
||||
try {
|
||||
$this->requireConnection();
|
||||
|
||||
// TODO: Do we need to include transactional statements here?
|
||||
$is_write = !preg_match('/^(SELECT|SHOW|EXPLAIN)\s/', $raw_query);
|
||||
if ($is_write) {
|
||||
AphrontWriteGuard::willWrite();
|
||||
}
|
||||
|
||||
$start = microtime(true);
|
||||
|
||||
$profiler = PhutilServiceProfiler::getInstance();
|
||||
$call_id = $profiler->beginServiceCall(
|
||||
array(
|
||||
'type' => 'query',
|
||||
'config' => $this->configuration,
|
||||
'query' => $raw_query,
|
||||
'write' => $is_write,
|
||||
));
|
||||
|
||||
$result = $this->rawQuery($raw_query);
|
||||
|
||||
$profiler->endServiceCall($call_id, array());
|
||||
|
||||
if ($this->nextError) {
|
||||
$result = null;
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
$this->lastResult = $result;
|
||||
break;
|
||||
}
|
||||
|
||||
$this->throwQueryException($this->connection);
|
||||
} catch (AphrontQueryConnectionLostException $ex) {
|
||||
if ($this->isInsideTransaction()) {
|
||||
// Zero out the transaction state to prevent a second exception
|
||||
// ("program exited with open transaction") from being thrown, since
|
||||
// we're about to throw a more relevant/useful one instead.
|
||||
$state = $this->getTransactionState();
|
||||
while ($state->getDepth()) {
|
||||
$state->decreaseDepth();
|
||||
}
|
||||
|
||||
// We can't close the connection before this because
|
||||
// isInsideTransaction() and getTransactionState() depend on the
|
||||
// connection.
|
||||
$this->close();
|
||||
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
$this->close();
|
||||
|
||||
if (!$retries) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function throwQueryException($connection) {
|
||||
if ($this->nextError) {
|
||||
$errno = $this->nextError;
|
||||
$error = 'Simulated error.';
|
||||
$this->nextError = null;
|
||||
} else {
|
||||
$errno = $this->getErrorCode($connection);
|
||||
$error = $this->getErrorDescription($connection);
|
||||
}
|
||||
|
||||
$exmsg = "#{$errno}: {$error}";
|
||||
|
||||
switch ($errno) {
|
||||
case 2013: // Connection Dropped
|
||||
throw new AphrontQueryConnectionLostException($exmsg);
|
||||
case 2006: // Gone Away
|
||||
$more = "This error may occur if your MySQL 'wait_timeout' ".
|
||||
"or 'max_allowed_packet' configuration values are set too low.";
|
||||
throw new AphrontQueryConnectionLostException("{$exmsg}\n\n{$more}");
|
||||
case 1213: // Deadlock
|
||||
case 1205: // Lock wait timeout exceeded
|
||||
throw new AphrontQueryDeadlockException($exmsg);
|
||||
case 1062: // Duplicate Key
|
||||
// NOTE: In some versions of MySQL we get a key name back here, but
|
||||
// older versions just give us a key index ("key 2") so it's not
|
||||
// portable to parse the key out of the error and attach it to the
|
||||
// exception.
|
||||
throw new AphrontQueryDuplicateKeyException($exmsg);
|
||||
case 1044: // Access denied to database
|
||||
case 1045: // Access denied (auth)
|
||||
case 1142: // Access denied to table
|
||||
case 1143: // Access denied to column
|
||||
throw new AphrontQueryAccessDeniedException($exmsg);
|
||||
case 1146: // No such table
|
||||
case 1049: // No such database
|
||||
case 1054: // Unknown column "..." in field list
|
||||
throw new AphrontQuerySchemaException($exmsg);
|
||||
default:
|
||||
// TODO: 1064 is syntax error, and quite terrible in production.
|
||||
throw new AphrontQueryException($exmsg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the next query to fail with a simulated error. This should be used
|
||||
* ONLY for unit tests.
|
||||
*/
|
||||
public function simulateErrorOnNextQuery($error) {
|
||||
$this->nextError = $error;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*
|
||||
* @phutil-external-symbol class mysqli
|
||||
*/
|
||||
final class AphrontMySQLiDatabaseConnection
|
||||
extends AphrontMySQLDatabaseConnectionBase {
|
||||
|
||||
public function escapeString($string) {
|
||||
return $this->requireConnection()->escape_string($string);
|
||||
}
|
||||
|
||||
public function getInsertID() {
|
||||
return $this->requireConnection()->insert_id;
|
||||
}
|
||||
|
||||
public function getAffectedRows() {
|
||||
return $this->requireConnection()->affected_rows;
|
||||
}
|
||||
|
||||
protected function closeConnection() {
|
||||
$this->requireConnection()->close();
|
||||
}
|
||||
|
||||
protected function connect() {
|
||||
if (!class_exists('mysqli', false)) {
|
||||
throw new Exception(
|
||||
"About to call new mysqli(), but the PHP MySQLi extension is not ".
|
||||
"available!");
|
||||
}
|
||||
|
||||
$user = $this->getConfiguration('user');
|
||||
$host = $this->getConfiguration('host');
|
||||
$database = $this->getConfiguration('database');
|
||||
|
||||
$pass = $this->getConfiguration('pass');
|
||||
if ($pass instanceof PhutilOpaqueEnvelope) {
|
||||
$pass = $pass->openEnvelope();
|
||||
}
|
||||
|
||||
$conn = @new mysqli(
|
||||
$host,
|
||||
$user,
|
||||
$pass,
|
||||
$database);
|
||||
|
||||
$errno = $conn->connect_errno;
|
||||
if ($errno) {
|
||||
$error = $conn->connect_error;
|
||||
throw new AphrontQueryConnectionException(
|
||||
"Attempt to connect to {$user}@{$host} failed with error ".
|
||||
"#{$errno}: {$error}.", $errno);
|
||||
}
|
||||
|
||||
$conn->set_charset('utf8');
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
protected function rawQuery($raw_query) {
|
||||
return @$this->requireConnection()->query($raw_query);
|
||||
}
|
||||
|
||||
protected function fetchAssoc($result) {
|
||||
return $result->fetch_assoc();
|
||||
}
|
||||
|
||||
protected function getErrorCode($connection) {
|
||||
return $connection->errno;
|
||||
}
|
||||
|
||||
protected function getErrorDescription($connection) {
|
||||
return $connection->error;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryAccessDeniedException
|
||||
extends AphrontQueryRecoverableException { }
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryConnectionException extends AphrontQueryException { }
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryConnectionLostException
|
||||
extends AphrontQueryRecoverableException { }
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryCountException extends AphrontQueryException { }
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryDeadlockException
|
||||
extends AphrontQueryRecoverableException { }
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryDuplicateKeyException extends AphrontQueryException {
|
||||
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
* @concrete-extensible
|
||||
*/
|
||||
class AphrontQueryException extends Exception { }
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryNotSupportedException extends AphrontQueryException {
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryObjectMissingException extends AphrontQueryException { }
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQueryParameterException extends AphrontQueryException {
|
||||
|
||||
private $query;
|
||||
|
||||
public function __construct($query, $message) {
|
||||
parent::__construct($message." Query: ".$query);
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
public function getQuery() {
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
abstract class AphrontQueryRecoverableException
|
||||
extends AphrontQueryException {
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group storage
|
||||
*/
|
||||
final class AphrontQuerySchemaException extends AphrontQueryException {
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue