[BUGFIX] Cast return value of postProcessDatabaseInsert to integer 18/56118/4
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:02:15 +0000 (22:02 +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/56118
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/core/Classes/DataHandling/DataHandler.php

index ddd8640..d61f851 100644 (file)
@@ -9123,8 +9123,38 @@ class DataHandler implements LoggerAwareInterface
             // 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;
     }
 
     /**