]> git.mxchange.org Git - friendica.git/blobdiff - src/Database/Database.php
Added description
[friendica.git] / src / Database / Database.php
index fe137b39bea375b88c8fd28f39291481c460670a..88d8d7d0f6ef87baa78cbc7f63dcd2cceeb65c15 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * @copyright Copyright (C) 2010-2021, the Friendica project
+ * @copyright Copyright (C) 2010-2022, the Friendica project
  *
  * @license GNU AGPL version 3 or any later version
  *
@@ -21,9 +21,9 @@
 
 namespace Friendica\Database;
 
-use Friendica\Core\Config\Cache;
+use Friendica\Core\Config\ValueObject\Cache;
 use Friendica\Core\System;
-use Friendica\Network\HTTPException\InternalServerErrorException;
+use Friendica\Network\HTTPException\ServiceUnavailableException;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Profiler;
 use mysqli;
@@ -49,7 +49,7 @@ class Database
        protected $connected = false;
 
        /**
-        * @var Cache
+        * @var \Friendica\Core\Config\ValueObject\Cache
         */
        protected $configCache;
        /**
@@ -114,6 +114,7 @@ class Database
                $pass    = trim($this->configCache->get('database', 'password'));
                $db      = trim($this->configCache->get('database', 'database'));
                $charset = trim($this->configCache->get('database', 'charset'));
+               $socket  = trim($this->configCache->get('database', 'socket')); 
 
                if (!(strlen($server) && strlen($user))) {
                        return false;
@@ -135,9 +136,14 @@ class Database
                                $connect .= ";charset=" . $charset;
                        }
 
+                       if ($socket) {
+                               $connect .= ";$unix_socket=" . $socket;
+                       }
+
                        try {
                                $this->connection = @new PDO($connect, $user, $pass, [PDO::ATTR_PERSISTENT => $persistent]);
                                $this->connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, $this->pdo_emulate_prepares);
+                               $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
                                $this->connected = true;
                        } catch (PDOException $e) {
                                $this->connected = false;
@@ -159,6 +165,11 @@ class Database
                                if ($charset) {
                                        $this->connection->set_charset($charset);
                                }
+
+                               if ($socket) {
+                                       $this->connection->set_socket($socket);
+                               }
+
                        }
                }
 
@@ -520,7 +531,7 @@ class Database
                $called_from_e = ($called_from['function'] == 'e');
 
                if (!isset($this->connection)) {
-                       throw new InternalServerErrorException('The Connection is empty, although connected is set true.');
+                       throw new ServiceUnavailableException('The Connection is empty, although connected is set true.');
                }
 
                switch ($this->driver) {
@@ -549,12 +560,14 @@ class Database
                                        break;
                                }
 
-                               foreach ($args as $param => $value) {
+                               foreach (array_keys($args) as $param) {
+                                       $data_type = PDO::PARAM_STR;
                                        if (is_int($args[$param])) {
                                                $data_type = PDO::PARAM_INT;
-                                       } else {
-                                               $data_type = PDO::PARAM_STR;
+                                       } elseif ($args[$param] !== null) {
+                                               $args[$param] = (string)$args[$param];
                                        }
+
                                        $stmt->bindParam($param, $args[$param], $data_type);
                                }
 
@@ -605,13 +618,16 @@ class Database
 
                                $param_types = '';
                                $values      = [];
-                               foreach ($args as $param => $value) {
+                               foreach (array_keys($args) as $param) {
                                        if (is_int($args[$param])) {
                                                $param_types .= 'i';
                                        } elseif (is_float($args[$param])) {
                                                $param_types .= 'd';
                                        } elseif (is_string($args[$param])) {
                                                $param_types .= 's';
+                                       } elseif (is_object($args[$param]) && method_exists($args[$param], '__toString')) {
+                                               $param_types .= 's';
+                                               $args[$param] = (string)$args[$param];
                                        } else {
                                                $param_types .= 'b';
                                        }
@@ -969,7 +985,7 @@ class Database
        }
 
        /**
-        * Insert a row into a table
+        * Insert a row into a table. Field value objects will be cast as string.
         *
         * @param string|array $table          Table name or array [schema => table]
         * @param array        $param          parameter array
@@ -1244,9 +1260,9 @@ class Database
        }
 
        /**
-        * Updates rows
+        * Updates rows in the database. Field value objects will be cast as string.
         *
-        * Updates rows in the database. When $old_fields is set to an array,
+        * When $old_fields is set to an array,
         * the system will only do an update if the fields in that array changed.
         *
         * Attention:
@@ -1362,6 +1378,45 @@ class Database
                return $this->toArray($this->select($table, $fields, $condition, $params));
        }
 
+       /**
+        * Escape fields, adding special treatment for "group by" handling
+        *
+        * @param array $fields 
+        * @param array $options 
+        * @return array 
+        */
+       private function escapeFields(array $fields, array $options)
+       {
+               // In the case of a "GROUP BY" we have to add all the ORDER fields to the fieldlist.
+               // This needs to done to apply the "ANY_VALUE(...)" treatment from below to them.
+               // Otherwise MySQL would report errors.
+               if (!empty($options['group_by']) && !empty($options['order'])) {
+                       foreach ($options['order'] as $key => $field) {
+                               if (!is_int($key)) {
+                                       if (!in_array($key, $fields)) {
+                                               $fields[] = $key;
+                                       }
+                               } else {
+                                       if (!in_array($field, $fields)) {
+                                               $fields[] = $field;
+                                       }
+                               }
+                       }
+               }
+
+               array_walk($fields, function(&$value, $key) use ($options)
+               {
+                       $field = $value;
+                       $value = '`' . str_replace('`', '``', $value) . '`';
+
+                       if (!empty($options['group_by']) && !in_array($field, $options['group_by'])) {
+                               $value = 'ANY_VALUE(' . $value . ') AS ' . $value;
+                       }
+               });
+
+               return $fields;
+       }
+
        /**
         * Select rows from a table
         *
@@ -1398,7 +1453,8 @@ class Database
                }
 
                if (count($fields) > 0) {
-                       $select_string = implode(', ', array_map([DBA::class, 'quoteIdentifier'], $fields));
+                       $fields = $this->escapeFields($fields, $params);
+                       $select_string = implode(', ', $fields);
                } else {
                        $select_string = '*';
                }
@@ -1561,9 +1617,9 @@ class Database
                        }
                }
 
-               return $fields; 
+               return $fields;
        }
-       
+
        /**
         * Returns the error number of the last query
         *