diff --git a/src/aphront/storage/connection/AphrontDatabaseConnection.php b/src/aphront/storage/connection/AphrontDatabaseConnection.php --- a/src/aphront/storage/connection/AphrontDatabaseConnection.php +++ b/src/aphront/storage/connection/AphrontDatabaseConnection.php @@ -8,6 +8,7 @@ implements PhutilQsprintfInterface { private $transactionState; + private $readOnly; abstract public function getInsertID(); abstract public function getAffectedRows(); @@ -37,6 +38,15 @@ return false; } + public function setReadOnly($read_only) { + $this->readOnly = $read_only; + return $this; + } + + public function getReadOnly() { + return $this->readOnly; + } + public function asyncQuery($raw_query) { throw new Exception(pht('Async queries are not supported.')); } diff --git a/src/aphront/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php b/src/aphront/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php --- a/src/aphront/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php +++ b/src/aphront/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php @@ -257,9 +257,17 @@ // (SELECT ...) UNION (SELECT ...) $is_write = !preg_match('/^[(]*(SELECT|SHOW|EXPLAIN)\s/', $raw_query); if ($is_write) { + if ($this->getReadOnly()) { + throw new Exception( + pht( + 'Attempting to issue a write query on a read-only '. + 'connection (to database "%s")!', + $this->getConfiguration('database'))); + } AphrontWriteGuard::willWrite(); return true; } + return false; }