Skip to content

Commit 809dbb3

Browse files
committed
Implement platform support for max params and insert syntax
1 parent 04441ca commit 809dbb3

12 files changed

Lines changed: 171 additions & 1 deletion

src/Connection.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,11 +535,20 @@ public function insert(string $table, array $data, array $types = []): int|strin
535535
*/
536536
public function insertMany(string $table, array $rows, array $types = []): int|string
537537
{
538+
$platform = $this->getDatabasePlatform();
539+
540+
if (! $platform->supportsBulkInserts($this)) {
541+
// TODO: custom exception
542+
throw new Exception('Bulk insert operation not supported by this platform');
543+
}
544+
538545
$numRows = count($rows);
539546
if ($numRows === 0) {
540547
return 0;
541548
}
542549

550+
$maxBoundParams = $platform->getMaximumAmountOfBoundParameters($this);
551+
543552
$columns = [];
544553
$values = [];
545554
$set = [];
@@ -551,7 +560,13 @@ public function insertMany(string $table, array $rows, array $types = []): int|s
551560
$first = false;
552561
$columns = array_keys($row);
553562
$columnCount = count($columns);
554-
$set = array_fill(0, count($columns), '?');
563+
564+
if ($columnCount * $numRows > $maxBoundParams) {
565+
// TODO: add a custom exception
566+
throw new Exception('Too many bound params');
567+
}
568+
569+
$set = array_fill(0, count($columns), '?');
555570
}
556571

557572
if ($columnCount !== count($row)) {

src/Driver/AbstractOracleDriver.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,23 @@
88
use Doctrine\DBAL\Driver\AbstractOracleDriver\EasyConnectString;
99
use Doctrine\DBAL\Driver\API\ExceptionConverter as ExceptionConverterInterface;
1010
use Doctrine\DBAL\Driver\API\OCI\ExceptionConverter;
11+
use Doctrine\DBAL\Platforms\Oracle23Platform;
1112
use Doctrine\DBAL\Platforms\OraclePlatform;
1213
use Doctrine\DBAL\ServerVersionProvider;
1314

15+
use function version_compare;
16+
1417
/**
1518
* Abstract base implementation of the {@see Driver} interface for Oracle based drivers.
1619
*/
1720
abstract class AbstractOracleDriver implements Driver
1821
{
1922
public function getDatabasePlatform(ServerVersionProvider $versionProvider): OraclePlatform
2023
{
24+
if (version_compare($versionProvider->getServerVersion(), '23.0.0', '>=')) {
25+
return new Oracle23Platform();
26+
}
27+
2128
return new OraclePlatform();
2229
}
2330

src/Platforms/AbstractMySQLPlatform.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,4 +929,13 @@ public function createSQLParser(): Parser
929929
{
930930
return new Parser(true);
931931
}
932+
933+
/**
934+
* Sources: https://dev.mysql.com/worklog/task/?id=1803
935+
* https://stackoverflow.com/a/6582902
936+
*/
937+
public function getMaximumAmountOfBoundParameters(Connection $connection): int
938+
{
939+
return 65535;
940+
}
932941
}

src/Platforms/AbstractPlatform.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2482,4 +2482,15 @@ public function createMetadataProvider(Connection $connection): MetadataProvider
24822482
* database schema according to the dialect of the platform.
24832483
*/
24842484
abstract public function createSchemaManager(Connection $connection): AbstractSchemaManager;
2485+
2486+
/** @throws Exception */
2487+
public function getMaximumAmountOfBoundParameters(Connection $connection): int
2488+
{
2489+
throw NotSupported::new(__METHOD__);
2490+
}
2491+
2492+
public function supportsBulkInserts(): bool
2493+
{
2494+
return true;
2495+
}
24852496
}

src/Platforms/DB2Platform.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,4 +597,12 @@ public function createSchemaManager(Connection $connection): DB2SchemaManager
597597
{
598598
return new DB2SchemaManager($connection, $this);
599599
}
600+
601+
/**
602+
* Source: https://www.bmc.com/blogs/db2-limits/
603+
*/
604+
public function getMaximumAmountOfBoundParameters(Connection $connection): int
605+
{
606+
return 16000;
607+
}
600608
}

src/Platforms/Oracle23Platform.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\DBAL\Platforms;
6+
7+
use Doctrine\DBAL\Connection;
8+
9+
class Oracle23Platform extends OraclePlatform
10+
{
11+
public function supportsBulkInserts(): bool
12+
{
13+
return true;
14+
}
15+
}

src/Platforms/OraclePlatform.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,4 +858,17 @@ public function createSchemaManager(Connection $connection): OracleSchemaManager
858858
{
859859
return new OracleSchemaManager($connection, $this);
860860
}
861+
862+
/**
863+
* https://docs.oracle.com/cd/B10501_01/appdev.920/a96624/e_limits.htm#LNPLS018
864+
*/
865+
public function getMaximumAmountOfBoundParameters(Connection $connection): int
866+
{
867+
return 64000;
868+
}
869+
870+
public function supportsBulkInserts(): bool
871+
{
872+
return false;
873+
}
861874
}

src/Platforms/PostgreSQLPlatform.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,4 +843,9 @@ public function createSchemaManager(Connection $connection): PostgreSQLSchemaMan
843843
{
844844
return new PostgreSQLSchemaManager($connection, $this);
845845
}
846+
847+
public function getMaximumAmountOfBoundParameters(Connection $connection): int
848+
{
849+
return 34464;
850+
}
846851
}

src/Platforms/SQLServerPlatform.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,4 +1334,12 @@ public function createSchemaManager(Connection $connection): SQLServerSchemaMana
13341334
{
13351335
return new SQLServerSchemaManager($connection, $this);
13361336
}
1337+
1338+
/**
1339+
* Source: https://learn.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server?view=sql-server-ver17
1340+
*/
1341+
public function getMaximumAmountOfBoundParameters(Connection $connection): int
1342+
{
1343+
return 2100;
1344+
}
13371345
}

src/Platforms/SQLitePlatform.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,4 +976,16 @@ public function getUnionSelectPartSQL(string $subQuery): string
976976
{
977977
return $subQuery;
978978
}
979+
980+
/**
981+
* @see https://www.sqlite.org/limits.html Secition 9:
982+
* To prevent excessive memory allocations, the maximum value of a host parameter number is SQLITE_MAX_VARIABLE_NUMBER,
983+
* which defaults to 999 for SQLite versions prior to 3.32.0 (2020-05-22) or 32766 for SQLite versions after 3.32.0.
984+
*
985+
* TODO: Should we create a new SQLite platform version which returns `32766` for post 3.32.0?, or read the SQLITE_MAX_VARIABLE_NUMBER?
986+
*/
987+
public function getMaximumAmountOfBoundParameters(Connection $connection): int
988+
{
989+
return 999;
990+
}
979991
}

0 commit comments

Comments
 (0)