Skip to content

Commit

Permalink
Fix handling of invalid sql query
Browse files Browse the repository at this point in the history
  • Loading branch information
eileenmcnaughton committed Feb 17, 2023
1 parent 53b7f64 commit 623da56
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 2 deletions.
9 changes: 9 additions & 0 deletions CRM/Core/Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ public function getExtraParams() {
return $this->errorData;
}

/**
* Get a message suitable to be presented to the user.
*
* @return string
*/
public function getUserMessage(): string {
return $this->getMessage();
}

/**
* Get error codes.
*
Expand Down
102 changes: 102 additions & 0 deletions CRM/Core/Exception/DBQueryInvalidException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
/*
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC. All rights reserved. |
| |
| This work is published under the GNU AGPLv3 license with some |
| permitted exceptions and without any warranty. For full license |
| and copyright information, see https://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/

/**
* Error when the syntax of a DB query is incorrect.
*
* @param string $message
* The human friendly error message.
* @param string $error_code
* A computer friendly error code. By convention, no space (but underscore allowed).
* ex: mandatory_missing, duplicate, invalid_format
* @param array $data
* - exception The original PEAR Exception
* - query The attempted mysql query
*/
class CRM_Core_Exception_DBQueryInvalidException extends CRM_Core_Exception {

/**
* Get a message suitable to be presented to the user.
*
* @return string
*/
public function getUserMessage(): string {
$matches = [];
preg_match('/\[nativecode=\d* \*\* (.*)]/', $this->getUserInfo(), $matches);
$errorMessage = $matches[1];
// Error 1054 is a missing field so safe to show. Other errors give the database name.
// It would be nice to point towards helpful tutorials like https://sebhastian.com/mysql-error-1054-fix/
return $this->getErrorCode() === 1054 ? ts('Invalid Query') . ' ' . $errorMessage : ts('Invalid Query') . ' ' . \DB::errorMessage($this->getPEARErrorCode());
}

/**
* @return \PEAR_Exception
*/
public function getPEARException(): PEAR_Exception {
return $this->getErrorData()['exception'];
}

/**
* @return int
*/
protected function getPEARErrorCode(): int {
return $this->getDBError()->getCode();
}

/**
* @return \DB_Error
*/
protected function getDBError(): DB_Error {
return $this->getPEARException()->getCause();
}

/**
* Get the mysql error code.
*
* @see https://mariadb.com/kb/en/mariadb-error-codes/
*
* @return int
*/
public function getErrorCode(): int {
$dbErrorMessage = $this->getUserInfo();
$matches = [];
preg_match('/\[nativecode=(\d*) /', $dbErrorMessage, $matches);
return (int) $matches[1];
}

/**
* Get the PEAR data intended to be use useful to the user.
*
* @return string
*/
protected function getUserInfo(): string {
return $this->getPEARException()->getCause()->getUserInfo();
}

/**
* Get the attempted sql.
*
* @return string
*/
public function getSQL(): string {
return $this->getDBError()->getDebugInfo();
}

/**
* Get the attempted sql.
*
* @return string
*/
public function getDebugInfo(): string {
return $this->getDBError()->getUserInfo();
}

}
7 changes: 6 additions & 1 deletion CRM/Import/DataSource/SQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,12 @@ public static function formRule($fields, $files, $form) {
public function initialize(): void {
$table = CRM_Utils_SQL_TempTable::build()->setDurable();
$tableName = $table->getName();
$table->createWithQuery($this->getSubmittedValue('sqlQuery'));
try {
$table->createWithQuery($this->getSubmittedValue('sqlQuery'));
}
catch (PEAR_Exception $e) {
throw new CRM_Core_Exception_DBQueryInvalidException($e->getMessage(), 0, ['query' => $this->getSubmittedValue('sqlQuery'), 'exception' => $e]);
}

// Get the names of the fields to be imported.
$columnsResult = CRM_Core_DAO::executeQuery(
Expand Down
8 changes: 7 additions & 1 deletion CRM/Import/Form/DataSource.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function preProcess(): void {
CRM_Utils_Number::formatUnitSize(ini_get('post_max_size'), TRUE);
$this->assign('importEntity', $this->getTranslatedEntity());
$this->assign('importEntities', $this->getTranslatedEntities());
CRM_Core_Session::singleton()->pushUserContext(CRM_Utils_System::url(CRM_Utils_System::currentPath(), 'reset=1'));
}

/**
Expand Down Expand Up @@ -176,7 +177,12 @@ protected function processDatasource(): void {
$this->flushDataSource();
$this->updateUserJobMetadata('submitted_values', $this->getSubmittedValues());
}
$this->instantiateDataSource();
try {
$this->instantiateDataSource();
}
catch (CRM_Core_Exception $e) {
CRM_Core_Error::statusBounce($e->getUserMessage());
}
}

/**
Expand Down

0 comments on commit 623da56

Please sign in to comment.