Add DBA::collapseCondition method
- Update Database->update for use with DBA::collapseCondition
This commit is contained in:
parent
5cc2dc7ca3
commit
ef6e9ef26b
2 changed files with 89 additions and 61 deletions
|
@ -529,67 +529,96 @@ class DBA
|
||||||
*/
|
*/
|
||||||
public static function buildCondition(array &$condition = [])
|
public static function buildCondition(array &$condition = [])
|
||||||
{
|
{
|
||||||
|
$condition = self::collapseCondition($condition);
|
||||||
|
|
||||||
$condition_string = '';
|
$condition_string = '';
|
||||||
if (count($condition) > 0) {
|
if (count($condition) > 0) {
|
||||||
reset($condition);
|
$condition_string = " WHERE (" . array_shift($condition) . ")";
|
||||||
$first_key = key($condition);
|
|
||||||
if (is_int($first_key)) {
|
|
||||||
$condition_string = " WHERE (" . array_shift($condition) . ")";
|
|
||||||
} else {
|
|
||||||
$new_values = [];
|
|
||||||
$condition_string = "";
|
|
||||||
foreach ($condition as $field => $value) {
|
|
||||||
if ($condition_string != "") {
|
|
||||||
$condition_string .= " AND ";
|
|
||||||
}
|
|
||||||
if (is_array($value)) {
|
|
||||||
if (count($value)) {
|
|
||||||
/* Workaround for MySQL Bug #64791.
|
|
||||||
* Never mix data types inside any IN() condition.
|
|
||||||
* In case of mixed types, cast all as string.
|
|
||||||
* Logic needs to be consistent with DBA::p() data types.
|
|
||||||
*/
|
|
||||||
$is_int = false;
|
|
||||||
$is_alpha = false;
|
|
||||||
foreach ($value as $single_value) {
|
|
||||||
if (is_int($single_value)) {
|
|
||||||
$is_int = true;
|
|
||||||
} else {
|
|
||||||
$is_alpha = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($is_int && $is_alpha) {
|
|
||||||
foreach ($value as &$ref) {
|
|
||||||
if (is_int($ref)) {
|
|
||||||
$ref = (string)$ref;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($ref); //Prevent accidental re-use.
|
|
||||||
}
|
|
||||||
|
|
||||||
$new_values = array_merge($new_values, array_values($value));
|
|
||||||
$placeholders = substr(str_repeat("?, ", count($value)), 0, -2);
|
|
||||||
$condition_string .= self::quoteIdentifier($field) . " IN (" . $placeholders . ")";
|
|
||||||
} else {
|
|
||||||
// Empty value array isn't supported by IN and is logically equivalent to no match
|
|
||||||
$condition_string .= "FALSE";
|
|
||||||
}
|
|
||||||
} elseif (is_null($value)) {
|
|
||||||
$condition_string .= self::quoteIdentifier($field) . " IS NULL";
|
|
||||||
} else {
|
|
||||||
$new_values[$field] = $value;
|
|
||||||
$condition_string .= self::quoteIdentifier($field) . " = ?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$condition_string = " WHERE (" . $condition_string . ")";
|
|
||||||
$condition = $new_values;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $condition_string;
|
return $condition_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collapse an associative array condition into a SQL string + parameters condition array.
|
||||||
|
*
|
||||||
|
* ['uid' => 1, 'network' => ['dspr', 'apub']]
|
||||||
|
*
|
||||||
|
* gets transformed into
|
||||||
|
*
|
||||||
|
* ["`uid` = ? AND `network` IN (?, ?)", 1, 'dspr', 'apub']
|
||||||
|
*
|
||||||
|
* @param array $condition
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function collapseCondition(array $condition)
|
||||||
|
{
|
||||||
|
// Ensures an always true condition is returned
|
||||||
|
if (count($condition) < 1) {
|
||||||
|
return ['1'];
|
||||||
|
}
|
||||||
|
|
||||||
|
reset($condition);
|
||||||
|
$first_key = key($condition);
|
||||||
|
|
||||||
|
if (is_int($first_key)) {
|
||||||
|
// Already collapsed
|
||||||
|
return $condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
$values = [];
|
||||||
|
$condition_string = "";
|
||||||
|
foreach ($condition as $field => $value) {
|
||||||
|
if ($condition_string != "") {
|
||||||
|
$condition_string .= " AND ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
|
if (count($value)) {
|
||||||
|
/* Workaround for MySQL Bug #64791.
|
||||||
|
* Never mix data types inside any IN() condition.
|
||||||
|
* In case of mixed types, cast all as string.
|
||||||
|
* Logic needs to be consistent with DBA::p() data types.
|
||||||
|
*/
|
||||||
|
$is_int = false;
|
||||||
|
$is_alpha = false;
|
||||||
|
foreach ($value as $single_value) {
|
||||||
|
if (is_int($single_value)) {
|
||||||
|
$is_int = true;
|
||||||
|
} else {
|
||||||
|
$is_alpha = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($is_int && $is_alpha) {
|
||||||
|
foreach ($value as &$ref) {
|
||||||
|
if (is_int($ref)) {
|
||||||
|
$ref = (string)$ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($ref); //Prevent accidental re-use.
|
||||||
|
}
|
||||||
|
|
||||||
|
$values = array_merge($values, array_values($value));
|
||||||
|
$placeholders = substr(str_repeat("?, ", count($value)), 0, -2);
|
||||||
|
$condition_string .= self::quoteIdentifier($field) . " IN (" . $placeholders . ")";
|
||||||
|
} else {
|
||||||
|
// Empty value array isn't supported by IN and is logically equivalent to no match
|
||||||
|
$condition_string .= "FALSE";
|
||||||
|
}
|
||||||
|
} elseif (is_null($value)) {
|
||||||
|
$condition_string .= self::quoteIdentifier($field) . " IS NULL";
|
||||||
|
} else {
|
||||||
|
$values[$field] = $value;
|
||||||
|
$condition_string .= self::quoteIdentifier($field) . " = ?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$condition = array_merge([$condition_string], array_values($values));
|
||||||
|
|
||||||
|
return $condition;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the SQL parameter string built from the provided parameter array
|
* @brief Returns the SQL parameter string built from the provided parameter array
|
||||||
*
|
*
|
||||||
|
|
|
@ -1327,10 +1327,6 @@ class Database
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$table_string = DBA::buildTableString($table);
|
|
||||||
|
|
||||||
$condition_string = DBA::buildCondition($condition);
|
|
||||||
|
|
||||||
if (is_bool($old_fields)) {
|
if (is_bool($old_fields)) {
|
||||||
$do_insert = $old_fields;
|
$do_insert = $old_fields;
|
||||||
|
|
||||||
|
@ -1361,13 +1357,16 @@ class Database
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$table_string = DBA::buildTableString($table);
|
||||||
|
|
||||||
|
$condition_string = DBA::buildCondition($condition);
|
||||||
|
|
||||||
$sql = "UPDATE " . $table_string . " SET "
|
$sql = "UPDATE " . $table_string . " SET "
|
||||||
. implode(" = ?, ", array_map([DBA::class, 'quoteIdentifier'], array_keys($fields))) . " = ?"
|
. implode(" = ?, ", array_map([DBA::class, 'quoteIdentifier'], array_keys($fields))) . " = ?"
|
||||||
. $condition_string;
|
. $condition_string;
|
||||||
|
|
||||||
$params1 = array_values($fields);
|
// Combines the updated fields parameter values with the condition parameter values
|
||||||
$params2 = array_values($condition);
|
$params = array_merge(array_values($fields), $condition);
|
||||||
$params = array_merge_recursive($params1, $params2);
|
|
||||||
|
|
||||||
return $this->e($sql, $params);
|
return $this->e($sql, $params);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue