Commit 59b55846 authored by Aaron Wells's avatar Aaron Wells

Make get_record warn instead of dying, by default

Bug 1515929: Usually when we use get_record(), we're
querying against a record that has a uniqueness constraint
guaranteeing that it is unique, in which case the PHP
code that dies on non-uniqueness is redundant.

In the remaining cases, we're dealing with records
that for some reason can't have a uniqueness constraint,
and the dying just causes the site to entirely stop
working, when it would be more useful to have it continue
to work but throw a warning message to the logs.

behatnotneeded: Covered by existing test cases

Change-Id: I264f72e3a8904293d78909410f68b29f2c78db3c
parent 1b2423a1
......@@ -12,6 +12,12 @@
defined('INTERNAL') || die();
/** Does not show debug warning if multiple records found (Use with care)*/
define('IGNORE_MULTIPLE', 0);
/** Show debug warning if multiple records found */
define('WARN_MULTIPLE', 1);
/** Throws an error if multiple records found */
define('ERROR_MULTIPLE', 2);
/**
* Return a table name, properly prefixed and escaped
*
......@@ -279,13 +285,16 @@ function count_records_sql($sql, $values=null) {
* @param string $value2 the value field2 must have (required if field2 is given, else optional).
* @param string $field3 the third field to check (optional).
* @param string $value3 the value field3 must have (required if field3 is given, else optional).
* @param int $strictness IGNORE_MULITPLE means no special action if multiple records found
* WARN_MULTIPLE means log a warning message if multiple records found
* ERROR_MULTIPLE means we will throw an exception if multiple records found.
* @return mixed a fieldset object containing the first mathcing record, or false if none found.
* @throws SQLException
*/
function get_record($table, $field1, $value1, $field2=null, $value2=null, $field3=null, $value3=null, $fields='*') {
function get_record($table, $field1, $value1, $field2=null, $value2=null, $field3=null, $value3=null, $fields='*', $strictness=WARN_MULTIPLE) {
$select = where_clause_prepared($field1, $field2, $field3);
$values = where_values_prepared($value1, $value2, $value3);
return get_record_sql('SELECT ' . $fields . ' FROM ' . db_table_name($table) . ' ' . $select, $values);
return get_record_sql('SELECT ' . $fields . ' FROM ' . db_table_name($table) . ' ' . $select, $values, $strictness);
}
/**
......@@ -296,16 +305,24 @@ function get_record($table, $field1, $value1, $field2=null, $value2=null, $field
*
* @param string $sql The SQL string you wish to be executed, should normally only return one record.
* @param array $values When using prepared statements, this is the value array (optional).
* @param int $strictness IGNORE_MULITPLE means no special action if multiple records found
* WARN_MULTIPLE means log a warning message if multiple records found
* ERROR_MULTIPLE means we will throw an exception if multiple records found.
* @return Found record as object. False if not found
* @throws SQLException
*/
function get_record_sql($sql, $values=null) {
function get_record_sql($sql, array $values=null, $strictness=WARN_MULTIPLE) {
$limitfrom = 0;
$limitnum = 0;
# regex borrowed from htdocs/lib/adodb/adodb-lib.inc.php
if (!preg_match('/\sLIMIT\s+[0-9]+/i', $sql)) {
$limitfrom = 0;
$limitnum = 2;
// Don't even bother checking for multiples if they don't care
if ($strictness == IGNORE_MULTIPLE) {
$limitnum = 1;
}
}
if (!$rs = get_recordset_sql($sql, $values, $limitfrom, $limitnum)) {
......@@ -314,16 +331,28 @@ function get_record_sql($sql, $values=null) {
$recordcount = $rs->RecordCount();
if ($recordcount == 0) { // Found no records
// Found no records
if ($recordcount == 0) {
return false;
}
else if ($recordcount == 1) { // Found one record
return (object)$rs->fields;
}
else { // Error: found more than one record
throw new SQLException('get_record_sql found more than one row. If you meant to retrieve more '
. 'than one record, use get_records_*, otherwise check your code or database for inconsistencies');
// Error: found more than one record
if ($recordcount > 1) {
$msg = 'get_record_sql found more than one row. If you meant to retrieve more '
. 'than one record, use get_records_*, otherwise check your code or database for inconsistencies';
switch ($strictness) {
case ERROR_MULTIPLE:
throw new SQLException($msg);
break;
case WARN_MULTIPLE:
log_debug($msg);
break;
case IGNORE_MULITPLE:
// Do nothing!
break;
}
}
return (object)$rs->fields;
}
/**
......@@ -333,14 +362,17 @@ function get_record_sql($sql, $values=null) {
* @param string $select A fragment of SQL to be used in a where clause in the SQL call.
* @param array $values When using prepared statements, this is the value array (optional).
* @param string $fields A comma separated list of fields to be returned from the chosen table.
* @param int $strictness IGNORE_MULITPLE means no special action if multiple records found
* WARN_MULTIPLE means log a warning message if multiple records found
* ERROR_MULTIPLE means we will throw an exception if multiple records found.
* @return object Returns an array of found records (as objects)
* @throws SQLException
*/
function get_record_select($table, $select='', $values=null, $fields='*') {
function get_record_select($table, $select='', array $values=null, $fields='*', $strictness=WARN_MULTIPLE) {
if ($select) {
$select = 'WHERE '. $select;
}
return get_record_sql('SELECT '. $fields .' FROM ' . db_table_name($table) .' '. $select, $values);
return get_record_sql('SELECT '. $fields .' FROM ' . db_table_name($table) .' '. $select, $values, $strictness);
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment