<?php
+/**
+ * @copyright Copyright (C) 2010-2022, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
namespace Friendica\Database;
use PDOStatement;
/**
- * @class MySQL database class
- *
* This class is for the low level database stuff that does driver specific things.
*/
class DBA
return DI::dba()->getConnection();
}
+ /**
+ * Return the database driver string
+ *
+ * @return string with either "pdo" or "mysqli"
+ */
+ public static function getDriver()
+ {
+ return DI::dba()->getDriver();
+ }
+
/**
* Returns the MySQL server version string
*
/**
* Executes a prepared statement that returns data
- * Example: $r = p("SELECT * FROM `item` WHERE `guid` = ?", $guid);
+ * Example: $r = p("SELECT * FROM `post` WHERE `guid` = ?", $guid);
*
* Please only use it with complicated queries.
* For all regular queries please use DBA::select or DBA::exists
/**
* Insert a row into a table
*
- * @param string|array $table Table name or array [schema => table]
- * @param array $param parameter array
- * @param bool $on_duplicate_update Do an update on a duplicate entry
+ * @param string|array $table Table name or array [schema => table]
+ * @param array $param parameter array
+ * @param int $duplicate_mode What to do on a duplicated entry
+ *
+ * @return boolean was the insert successful?
+ * @throws \Exception
+ */
+ public static function insert($table, array $param, int $duplicate_mode = Database::INSERT_DEFAULT)
+ {
+ return DI::dba()->insert($table, $param, $duplicate_mode);
+ }
+
+ /**
+ * Inserts a row with the provided data in the provided table.
+ * If the data corresponds to an existing row through a UNIQUE or PRIMARY index constraints, it updates the row instead.
+ *
+ * @param string|array $table Table name or array [schema => table]
+ * @param array $param parameter array
*
* @return boolean was the insert successful?
* @throws \Exception
*/
- public static function insert($table, $param, $on_duplicate_update = false)
+ public static function replace($table, $param)
{
- return DI::dba()->insert($table, $param, $on_duplicate_update);
+ return DI::dba()->replace($table, $param);
}
/**
*
* @param string|array $table Table name
* @param array $conditions Field condition(s)
- * @param array $options
- * - cascade: If true we delete records in other tables that depend on the one we're deleting through
- * relations (default: true)
*
* @return boolean was the delete successful?
* @throws \Exception
* @param string|array $table Table name or array [schema => table]
* @param array $fields contains the fields that are updated
* @param array $condition condition array with the key values
- * @param array|boolean $old_fields array with the old field values that are about to be replaced (true = update on duplicate)
+ * @param array|boolean $old_fields array with the old field values that are about to be replaced (true = update on duplicate, false = don't update identical fields)
*
* @return boolean was the update successfull?
* @throws \Exception
* @return boolean|object
*
* Example:
- * $table = "item";
+ * $table = "post";
* $fields = array("id", "uri", "uid", "network");
*
* $condition = array("uid" => 1, "network" => 'dspr');
* @return int
*
* Example:
- * $table = "item";
+ * $table = "post";
*
* $condition = ["uid" => 1, "network" => 'dspr'];
* or:
* Returns the SQL condition string built from the provided condition array
*
* This function operates with two modes.
- * - Supplied with a filed/value associative array, it builds simple strict
+ * - Supplied with a field/value associative array, it builds simple strict
* equality conditions linked by AND.
* - Supplied with a flat list, the first element is the condition string and
* the following arguments are the values to be interpolated
return $condition;
}
+ /**
+ * Merges the provided conditions into a single collapsed one
+ *
+ * @param array ...$conditions One or more condition arrays
+ * @return array A collapsed condition
+ * @see DBA::collapseCondition() for the condition array formats
+ */
+ public static function mergeConditions(array ...$conditions)
+ {
+ if (count($conditions) == 1) {
+ return current($conditions);
+ }
+
+ $conditionStrings = [];
+ $result = [];
+
+ foreach ($conditions as $key => $condition) {
+ if (!$condition) {
+ continue;
+ }
+
+ $condition = self::collapseCondition($condition);
+
+ $conditionStrings[] = array_shift($condition);
+ // The result array holds the eventual parameter values
+ $result = array_merge($result, $condition);
+ }
+
+ if (count($conditionStrings)) {
+ // We prepend the condition string at the end to form a collapsed condition array again
+ array_unshift($result, implode(' AND ', $conditionStrings));
+ }
+
+ return $result;
+ }
+
/**
* Returns the SQL parameter string built from the provided parameter array
*
+ * Expected format for each key:
+ *
+ * group_by:
+ * - list of column names
+ *
+ * order:
+ * - numeric keyed column name => ASC
+ * - associative element with boolean value => DESC (true), ASC (false)
+ * - associative element with string value => 'ASC' or 'DESC' literally
+ *
+ * limit:
+ * - single numeric value => count
+ * - list with two numeric values => offset, count
+ *
* @param array $params
* @return string
*/
$order_string = '';
if (isset($params['order'])) {
$order_string = " ORDER BY ";
- foreach ($params['order'] AS $fields => $order) {
+ foreach ($params['order'] as $fields => $order) {
if ($order === 'RAND()') {
$order_string .= "RAND(), ";
} elseif (!is_int($fields)) {
- $order_string .= self::quoteIdentifier($fields) . " " . ($order ? "DESC" : "ASC") . ", ";
+ if ($order !== 'DESC' && $order !== 'ASC') {
+ $order = $order ? 'DESC' : 'ASC';
+ }
+
+ $order_string .= self::quoteIdentifier($fields) . " " . $order . ", ";
} else {
$order_string .= self::quoteIdentifier($order) . ", ";
}
/**
* Fills an array with data from a query
*
- * @param object $stmt statement object
- * @param bool $do_close
+ * @param object $stmt statement object
+ * @param bool $do_close Close database connection after last row
+ * @param int $count maximum number of rows to be fetched
+ *
* @return array Data array
*/
- public static function toArray($stmt, $do_close = true)
+ public static function toArray($stmt, $do_close = true, int $count = 0)
{
- return DI::dba()->toArray($stmt, $do_close);
+ return DI::dba()->toArray($stmt, $do_close, $count);
+ }
+
+ /**
+ * Cast field types according to the table definition
+ *
+ * @param string $table
+ * @param array $fields
+ * @return array casted fields
+ */
+ public static function castFields(string $table, array $fields)
+ {
+ return DI::dba()->castFields($table, $fields);
}
/**
return DI::dba()->processlist();
}
+ /**
+ * Fetch a database variable
+ *
+ * @param string $name
+ * @return string content
+ */
+ public static function getVariable(string $name)
+ {
+ return DI::dba()->getVariable($name);
+ }
+
/**
* Checks if $array is a filled array with at least one entry.
*