Skip to content

Commit

Permalink
[Core-Database] added 2 new functions to help avoid code duplication (#…
Browse files Browse the repository at this point in the history
…3428)

This adds 2 new functions to the database.class.inc that build on the pselect() and pselectCol() in order to return an array indexed by a selected primary key. These functions are meant to replace the multitude of places in the code where the pselect() and pselectCol() result is ran through a foreach loop in order to extract and re-index the array using its primary keys.

The necessary Exceptions are thrown to avoid data being overwritten in the built array and misuse of the function in general.
  • Loading branch information
ridz1208 authored and driusan committed Feb 9, 2018
1 parent d268ddc commit 48f3faf
Showing 1 changed file with 149 additions and 0 deletions.
149 changes: 149 additions & 0 deletions php/libraries/Database.class.inc
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,77 @@ class Database
return $result;
}

/**
* Runs an SQL select statement as a prepared query and re-indexes
* the results using the given unique non-nullable key.
*
* @param string $query The SQL SELECT query to be run
* @param array $params Values to use for binding to the prepared statement
* @param string $uniqueKey Key to use when re-indexing, this key must be a
* single column, must be unique and must not be
* nullable
*
* @throws LorisException If the supplied key is empty or null
* @throws DatabaseException If the key is not part of the query itself
* @throws DatabaseException If the key is not unique within the resulting set
*
* @return array An array of arrays containing the data. The outermost array is
* associative and uses the supplied $uniqueKey parameter as
* a key for each of the sub-arrays with the format
* rowPrimaryKey=>rowValuesArray. Each nested array represents
* a row from the returned by the query. Each element in the
* nested array is an associative array representing the row in
* the format ColumnName => Value
*/
function pselectWithIndexKey($query, $params, $uniqueKey)
{
if (is_null($uniqueKey) || empty($uniqueKey)) {
throw new LorisException(
"The pselectWithIndexKey() function expects the uniqueKey parameter
to not be null or empty. If re-indexing on the primary key is
not necessary please use the pselect() function instead."
);
}

$result = $this->pselect($query, $params);

if (empty($result)) {
return $result;
}

$filteredResult = array();
// re-order the return array
foreach ($result as $row) {
// Check first that the row contains the primary key supplied
if (!array_key_exists($uniqueKey, $row)) {
throw new DatabaseException(
"The query supplied to pselectWithIndexKey() does not contain
the unique key to re-index on. Make sure to supply the
appropriate key in the SELECT statement to match the supplied
parameter of this function",
$query
);
}

// Check that the primary key is indeed unique to avoid overriding data
// in the result array
if (isset($filteredResult[$row[$uniqueKey]])) {
throw new DatabaseException(
"The uniqueKey supplied to pselectWithIndexKey() does not appear
to be unique or is nullable. This function expects the key to
be both UNIQUE and NOT NULL.",
$query
);
}

// If you get here, we just need to build the new array
$filteredResult[$row[$uniqueKey]] = $row;
unset($filteredResult[$row[$uniqueKey]][$uniqueKey]);
}

return $filteredResult;
}

/**
* Runs a query as a prepared statement and returns the first row as an
* associative array. Automatically adds a limit clause to the query being
Expand Down Expand Up @@ -772,6 +843,8 @@ class Database
* @param string $query The SQL SELECT query to be run
* @param array $params Values to use for binding to prepared statement
*
* @throws DatabaseException if the query selected more than one column
*
* @return array Associative array of form rowID=>value containing all values
* for the first element of the select statement
*/
Expand All @@ -796,6 +869,82 @@ class Database
return $result;
}

/**
* Runs an SQL select statement as a prepared query and re-indexes
* the results using the given unique non-nullable key in the same
* format as the pselectCol() function.
*
* @param string $query The SQL SELECT query to be run
* @param array $params Values to use for binding to the prepared statement
* @param string $uniqueKey Key to use when re-indexing, this key must be a
* single column, must be unique and must not be
* nullable
*
* @throws LorisException If the supplied key is empty or null
* @throws DatabaseException If the key is not part of the query itself or
* if there are not exactly 2 columns selected
* @throws DatabaseException If the key is not unique within the resulting set
*
* @return array Associative array of form uniqueKey=>value containing all
* value for the non-uniqueKey element of the select statement
*/
function pselectColWithIndexKey($query, $params, $uniqueKey)
{
if (is_null($uniqueKey) || empty($uniqueKey)) {
throw new LorisException(
"The pselectColWithIndexKey() function expects the uniqueKey
parameter to not be null or empty. If re-indexing on the primary
key is not necessary please use the pselectCol() function instead."
);
}

$result = $this->pselect($query, $params);

if (empty($result)) {
return $result;
}

$filteredResult = array();
// re-order the return array
foreach ($result as $row) {
$colNumber = count($row);
// Check first that the row contains the primary key supplied
if (!array_key_exists($uniqueKey, $row) || $colNumber !== 2) {
throw new DatabaseException(
"The query supplied to pselectColWithIndexKey() should only
contain the unique key and one other column in the SELECT
clause. Make sure to supply the appropriate key in the SELECT
statement to match the supplied parameter of this function.",
$query
);
}

// Check that the primary key is indeed unique to avoid overriding data
// in the result array
if (isset($filteredResult[$row[$uniqueKey]])) {
throw new DatabaseException(
"The uniqueKey supplied to pselectColWithIndexKey() does not
appear to be unique or is nullable. This function expects the
key to be both UNIQUE and NOT NULL.",
$query
);
}

// Store the value of the key for this specific row then unset that
// value from the $row array so that the only element remaining is
// the column desired and its value for this row
$uniqueKeyValue = $row[$uniqueKey];
unset($row[$uniqueKey]);

// Note: reset() rewinds array's internal pointer to the first element
// and returns the value of the first array element, in this case the
// desired column value
$filteredResult[$uniqueKeyValue] = reset($row);
}

return $filteredResult;
}

/**
* Runs a query as a prepared statement and returns the value of the first
* column of the first row
Expand Down

0 comments on commit 48f3faf

Please sign in to comment.