[BUGFIX] Cast return value of postProcessDatabaseInsert to integer 95/56195/2
authorSusanne Moog <susanne.moog@typo3.org>
Thu, 15 Mar 2018 14:03:13 +0000 (15:03 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Thu, 15 Mar 2018 21:26:35 +0000 (22:26 +0100)
Connection::lastInsertId returns a string but
DataHandler::postProcessDatabaseInsert has a strict integer return
value, so the value has to be casted to integer on return.

Additionally, when using sqlserver doctrine fails to fetch the last
inserted id under certain circumstances. An additional retrieval
method was introduced to mitigate that error.

Resolves: #84219
Releases: master, 8.7
Change-Id: I94dc0dc964aef26380703f641691c6a80ec5180d
Reviewed-on: https://review.typo3.org/56195
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/core/Classes/DataHandling/DataHandler.php

index 039abc8..41bec2c 100644 (file)
@@ -9195,8 +9195,38 @@ class DataHandler
             // Return the actual ID we forced on insert as a surrogate.
             return $suggestedUid;
         }
+        if ($connection->getDatabasePlatform() instanceof SQLServerPlatform) {
+            return $this->postProcessSqlServerInsert($connection, $tableName);
+        }
+        $id = $connection->lastInsertId($tableName);
+        return (int)$id;
+    }
 
-        return $connection->lastInsertId($tableName);
+    /**
+     * Get the last insert ID from sql server
+     *
+     * - first checks whether doctrine might be able to fetch the ID from the
+     * sequence table
+     * - if that does not succeed it manually selects the current IDENTITY value
+     * from a table
+     * - returns 0 if both fail
+     *
+     * @param \TYPO3\CMS\Core\Database\Connection $connection
+     * @param string $tableName
+     * @return int
+     * @throws \Doctrine\DBAL\DBALException
+     */
+    protected function postProcessSqlServerInsert(Connection $connection, string $tableName): int
+    {
+        $id = $connection->lastInsertId($tableName);
+        if (!((int)$id > 0)) {
+            $table = $connection->quoteIdentifier($tableName);
+            $result = $connection->executeQuery('SELECT IDENT_CURRENT(\'' . $table . '\') AS id')->fetch();
+            if (isset($result['id']) && $result['id'] > 0) {
+                $id = $result['id'];
+            }
+        }
+        return (int)$id;
     }
 
     /**