diff --git a/Classes/Core/Functional/Framework/DataHandling/DataSet.php b/Classes/Core/Functional/Framework/DataHandling/DataSet.php index 02273a20..43615e6b 100644 --- a/Classes/Core/Functional/Framework/DataHandling/DataSet.php +++ b/Classes/Core/Functional/Framework/DataHandling/DataSet.php @@ -69,24 +69,39 @@ public static function import(string $path): void foreach ($dataSet->getTableNames() as $tableName) { $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($tableName); $platform = $connection->getDatabasePlatform(); - // @todo Check if we can use the cached schema information here instead. - $tableDetails = $connection->createSchemaManager()->introspectTable($tableName); - foreach ($dataSet->getElements($tableName) as $element) { + $columnInfos = $connection->getSchemaInformation()->listTableColumnInfos($tableName); + $autoIncrementColumnName = null; + foreach ($columnInfos as $columnInfo) { + if ($columnInfo->autoincrement) { + $autoIncrementColumnName = $columnInfo->name; + break; + } + } + $fields = $dataSet->getFields($tableName); + $elements = $dataSet->getElements($tableName); + if ($fields !== null && $elements !== []) { // Some DBMS like postgresql are picky about inserting blob types with correct cast, setting // types correctly (like Connection::PARAM_LOB) allows doctrine to create valid SQL $types = []; - foreach ($element as $columnName => $columnValue) { - $types[$columnName] = $columnType = $tableDetails->getColumn($columnName)->getType(); - // JSON-Field data is converted (json-encode'd) within $connection->insert(), and since json field - // data can only be provided json encoded in the csv dataset files, we need to decode them here. - if ($columnValue !== null && $columnType instanceof JsonType) { - $element[$columnName] = $columnType->convertToPHPValue($columnValue, $platform); + foreach ($fields as $columnName) { + $types[$columnName] = $columnType = $columnInfos[$columnName]->getType(); + // JSON-Field data is converted (json-encode'd) within $connection->bulkInsert(), and since json + // field data can only be provided json encoded in the csv dataset files, we need to decode them + // here. + if ($columnType instanceof JsonType) { + foreach ($elements as &$element) { + if ($element[$columnName] !== null) { + $element[$columnName] = $columnType->convertToPHPValue($element[$columnName], $platform); + } + } + unset($element); } } - // Insert the row - $connection->insert($tableName, $element, $types); + $connection->bulkInsert($tableName, $elements, $fields, $types); + } + if ($autoIncrementColumnName !== null) { + Testbase::resetTableSequences($connection, $tableName, $autoIncrementColumnName); } - Testbase::resetTableSequences($connection, $tableName); } } diff --git a/Classes/Core/Testbase.php b/Classes/Core/Testbase.php index 4c736e64..02dac9c5 100644 --- a/Classes/Core/Testbase.php +++ b/Classes/Core/Testbase.php @@ -914,14 +914,27 @@ public function createDatabaseStructure(ContainerInterface $container): void } /** - * Perform post processing of database tables after an insert has been performed. - * Doing this once per insert is rather slow, but due to the soft reference behavior - * this needs to be done after every row to ensure consistent results. + * Synchronize an auto-increment sequence after inserting records with explicit IDs. */ - public static function resetTableSequences(Connection $connection, string $tableName): void - { + public static function resetTableSequences( + Connection $connection, + string $tableName, + ?string $autoIncrementColumnName = null + ): void { $platform = $connection->getDatabasePlatform(); if ($platform instanceof DoctrinePostgreSQLPlatform) { + if ($autoIncrementColumnName !== null) { + $connection->executeStatement( + sprintf( + 'SELECT SETVAL(PG_GET_SERIAL_SEQUENCE(%s, %s), COALESCE(MAX(%s), 0)+1, FALSE) FROM %s', + $connection->quote($connection->quoteIdentifier($tableName)), + $connection->quote($autoIncrementColumnName), + $connection->quoteIdentifier($autoIncrementColumnName), + $connection->quoteIdentifier($tableName) + ) + ); + return; + } $queryBuilder = $connection->createQueryBuilder(); $queryBuilder->getRestrictions()->removeAll(); $row = $queryBuilder->select('PGT.schemaname', 'S.relname', 'C.attname', 'T.relname AS tablename')