Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F1433059
Connection.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
63 KB
Referenced Files
None
Subscribers
None
Connection.php
View Options
<?php
namespace
Doctrine\DBAL
;
use
Closure
;
use
Doctrine\Common\EventManager
;
use
Doctrine\DBAL\Cache\ArrayResult
;
use
Doctrine\DBAL\Cache\CacheException
;
use
Doctrine\DBAL\Cache\QueryCacheProfile
;
use
Doctrine\DBAL\Driver\API\ExceptionConverter
;
use
Doctrine\DBAL\Driver\Connection
as
DriverConnection
;
use
Doctrine\DBAL\Driver\ServerInfoAwareConnection
;
use
Doctrine\DBAL\Driver\Statement
as
DriverStatement
;
use
Doctrine\DBAL\Event\TransactionBeginEventArgs
;
use
Doctrine\DBAL\Event\TransactionCommitEventArgs
;
use
Doctrine\DBAL\Event\TransactionRollBackEventArgs
;
use
Doctrine\DBAL\Exception\ConnectionLost
;
use
Doctrine\DBAL\Exception\DriverException
;
use
Doctrine\DBAL\Exception\InvalidArgumentException
;
use
Doctrine\DBAL\Platforms\AbstractPlatform
;
use
Doctrine\DBAL\Query\Expression\ExpressionBuilder
;
use
Doctrine\DBAL\Query\QueryBuilder
;
use
Doctrine\DBAL\Schema\AbstractSchemaManager
;
use
Doctrine\DBAL\Schema\DefaultSchemaManagerFactory
;
use
Doctrine\DBAL\Schema\LegacySchemaManagerFactory
;
use
Doctrine\DBAL\Schema\SchemaManagerFactory
;
use
Doctrine\DBAL\SQL\Parser
;
use
Doctrine\DBAL\Types\Type
;
use
Doctrine\Deprecations\Deprecation
;
use
LogicException
;
use
SensitiveParameter
;
use
Throwable
;
use
Traversable
;
use
function
array_key_exists
;
use
function
assert
;
use
function
count
;
use
function
get_class
;
use
function
implode
;
use
function
is_array
;
use
function
is_int
;
use
function
is_string
;
use
function
key
;
use
function
method_exists
;
use
function
sprintf
;
/**
* A database abstraction-level connection that implements features like events, transaction isolation levels,
* configuration, emulated transaction nesting, lazy connecting and more.
*
* @psalm-import-type Params from DriverManager
* @psalm-consistent-constructor
*/
class
Connection
{
/**
* Represents an array of ints to be expanded by Doctrine SQL parsing.
*
* @deprecated Use {@see ArrayParameterType::INTEGER} instead.
*/
public
const
PARAM_INT_ARRAY
=
ArrayParameterType
::
INTEGER
;
/**
* Represents an array of strings to be expanded by Doctrine SQL parsing.
*
* @deprecated Use {@see ArrayParameterType::STRING} instead.
*/
public
const
PARAM_STR_ARRAY
=
ArrayParameterType
::
STRING
;
/**
* Represents an array of ascii strings to be expanded by Doctrine SQL parsing.
*
* @deprecated Use {@see ArrayParameterType::ASCII} instead.
*/
public
const
PARAM_ASCII_STR_ARRAY
=
ArrayParameterType
::
ASCII
;
/**
* Offset by which PARAM_* constants are detected as arrays of the param type.
*
* @internal Should be used only within the wrapper layer.
*/
public
const
ARRAY_PARAM_OFFSET
=
100
;
/**
* The wrapped driver connection.
*
* @var DriverConnection|null
*/
protected
$_conn
;
/** @var Configuration */
protected
$_config
;
/**
* @deprecated
*
* @var EventManager
*/
protected
$_eventManager
;
/**
* @deprecated Use {@see createExpressionBuilder()} instead.
*
* @var ExpressionBuilder
*/
protected
$_expr
;
/**
* The current auto-commit mode of this connection.
*/
private
bool
$autoCommit
=
true
;
/**
* The transaction nesting level.
*/
private
int
$transactionNestingLevel
=
0
;
/**
* The currently active transaction isolation level or NULL before it has been determined.
*
* @var TransactionIsolationLevel::*|null
*/
private
$transactionIsolationLevel
;
/**
* If nested transactions should use savepoints.
*/
private
bool
$nestTransactionsWithSavepoints
=
false
;
/**
* The parameters used during creation of the Connection instance.
*
* @var array<string,mixed>
* @psalm-var Params
*/
private
array
$params
;
/**
* The database platform object used by the connection or NULL before it's initialized.
*/
private
?
AbstractPlatform
$platform
=
null
;
private
?
ExceptionConverter
$exceptionConverter
=
null
;
private
?
Parser
$parser
=
null
;
/**
* The schema manager.
*
* @deprecated Use {@see createSchemaManager()} instead.
*
* @var AbstractSchemaManager|null
*/
protected
$_schemaManager
;
/**
* The used DBAL driver.
*
* @var Driver
*/
protected
$_driver
;
/**
* Flag that indicates whether the current transaction is marked for rollback only.
*/
private
bool
$isRollbackOnly
=
false
;
private
SchemaManagerFactory
$schemaManagerFactory
;
/**
* Initializes a new instance of the Connection class.
*
* @internal The connection can be only instantiated by the driver manager.
*
* @param array<string,mixed> $params The connection parameters.
* @param Driver $driver The driver to use.
* @param Configuration|null $config The configuration, optional.
* @param EventManager|null $eventManager The event manager, optional.
* @psalm-param Params $params
*
* @throws Exception
*/
public
function
__construct
(
#[SensitiveParameter]
array
$params
,
Driver
$driver
,
?
Configuration
$config
=
null
,
?
EventManager
$eventManager
=
null
)
{
$this
->
_driver
=
$driver
;
$this
->
params
=
$params
;
// Create default config and event manager if none given
$config
??=
new
Configuration
();
$eventManager
??=
new
EventManager
();
$this
->
_config
=
$config
;
$this
->
_eventManager
=
$eventManager
;
if
(
isset
(
$params
[
'platform'
]))
{
if
(!
$params
[
'platform'
]
instanceof
Platforms\AbstractPlatform
)
{
throw
Exception
::
invalidPlatformType
(
$params
[
'platform'
]);
}
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/5699'
,
'The "platform" connection parameter is deprecated.'
.
' Use a driver middleware that would instantiate the platform instead.'
,
);
$this
->
platform
=
$params
[
'platform'
];
$this
->
platform
->
setEventManager
(
$this
->
_eventManager
);
$this
->
platform
->
setDisableTypeComments
(
$config
->
getDisableTypeComments
());
}
$this
->
_expr
=
$this
->
createExpressionBuilder
();
$this
->
autoCommit
=
$config
->
getAutoCommit
();
$schemaManagerFactory
=
$config
->
getSchemaManagerFactory
();
if
(
$schemaManagerFactory
===
null
)
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/5812'
,
'Not configuring a schema manager factory is deprecated.'
.
' Use %s which is going to be the default in DBAL 4.'
,
DefaultSchemaManagerFactory
::
class
,
);
$schemaManagerFactory
=
new
LegacySchemaManagerFactory
();
}
$this
->
schemaManagerFactory
=
$schemaManagerFactory
;
}
/**
* Gets the parameters used during instantiation.
*
* @internal
*
* @return array<string,mixed>
* @psalm-return Params
*/
public
function
getParams
()
{
return
$this
->
params
;
}
/**
* Gets the name of the currently selected database.
*
* @return string|null The name of the database or NULL if a database is not selected.
* The platforms which don't support the concept of a database (e.g. embedded databases)
* must always return a string as an indicator of an implicitly selected database.
*
* @throws Exception
*/
public
function
getDatabase
()
{
$platform
=
$this
->
getDatabasePlatform
();
$query
=
$platform
->
getDummySelectSQL
(
$platform
->
getCurrentDatabaseExpression
());
$database
=
$this
->
fetchOne
(
$query
);
assert
(
is_string
(
$database
)
||
$database
===
null
);
return
$database
;
}
/**
* Gets the DBAL driver instance.
*
* @return Driver
*/
public
function
getDriver
()
{
return
$this
->
_driver
;
}
/**
* Gets the Configuration used by the Connection.
*
* @return Configuration
*/
public
function
getConfiguration
()
{
return
$this
->
_config
;
}
/**
* Gets the EventManager used by the Connection.
*
* @deprecated
*
* @return EventManager
*/
public
function
getEventManager
()
{
Deprecation
::
triggerIfCalledFromOutside
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/5784'
,
'%s is deprecated.'
,
__METHOD__
,
);
return
$this
->
_eventManager
;
}
/**
* Gets the DatabasePlatform for the connection.
*
* @return AbstractPlatform
*
* @throws Exception
*/
public
function
getDatabasePlatform
()
{
if
(
$this
->
platform
===
null
)
{
$this
->
platform
=
$this
->
detectDatabasePlatform
();
$this
->
platform
->
setEventManager
(
$this
->
_eventManager
);
$this
->
platform
->
setDisableTypeComments
(
$this
->
_config
->
getDisableTypeComments
());
}
return
$this
->
platform
;
}
/**
* Creates an expression builder for the connection.
*/
public
function
createExpressionBuilder
():
ExpressionBuilder
{
return
new
ExpressionBuilder
(
$this
);
}
/**
* Gets the ExpressionBuilder for the connection.
*
* @deprecated Use {@see createExpressionBuilder()} instead.
*
* @return ExpressionBuilder
*/
public
function
getExpressionBuilder
()
{
Deprecation
::
triggerIfCalledFromOutside
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/4515'
,
'Connection::getExpressionBuilder() is deprecated,'
.
' use Connection::createExpressionBuilder() instead.'
,
);
return
$this
->
_expr
;
}
/**
* Establishes the connection with the database.
*
* @internal This method will be made protected in DBAL 4.0.
*
* @return bool TRUE if the connection was successfully established, FALSE if
* the connection is already open.
*
* @throws Exception
*
* @psalm-assert !null $this->_conn
*/
public
function
connect
()
{
Deprecation
::
triggerIfCalledFromOutside
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/4966'
,
'Public access to Connection::connect() is deprecated.'
,
);
if
(
$this
->
_conn
!==
null
)
{
return
false
;
}
try
{
$this
->
_conn
=
$this
->
_driver
->
connect
(
$this
->
params
);
}
catch
(
Driver\Exception
$e
)
{
throw
$this
->
convertException
(
$e
);
}
if
(
$this
->
autoCommit
===
false
)
{
$this
->
beginTransaction
();
}
if
(
$this
->
_eventManager
->
hasListeners
(
Events
::
postConnect
))
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/5784'
,
'Subscribing to %s events is deprecated. Implement a middleware instead.'
,
Events
::
postConnect
,
);
$eventArgs
=
new
Event\ConnectionEventArgs
(
$this
);
$this
->
_eventManager
->
dispatchEvent
(
Events
::
postConnect
,
$eventArgs
);
}
return
true
;
}
/**
* Detects and sets the database platform.
*
* Evaluates custom platform class and version in order to set the correct platform.
*
* @throws Exception If an invalid platform was specified for this connection.
*/
private
function
detectDatabasePlatform
():
AbstractPlatform
{
$version
=
$this
->
getDatabasePlatformVersion
();
if
(
$version
!==
null
)
{
assert
(
$this
->
_driver
instanceof
VersionAwarePlatformDriver
);
return
$this
->
_driver
->
createDatabasePlatformForVersion
(
$version
);
}
return
$this
->
_driver
->
getDatabasePlatform
();
}
/**
* Returns the version of the related platform if applicable.
*
* Returns null if either the driver is not capable to create version
* specific platform instances, no explicit server version was specified
* or the underlying driver connection cannot determine the platform
* version without having to query it (performance reasons).
*
* @return string|null
*
* @throws Throwable
*/
private
function
getDatabasePlatformVersion
()
{
// Driver does not support version specific platforms.
if
(!
$this
->
_driver
instanceof
VersionAwarePlatformDriver
)
{
return
null
;
}
// Explicit platform version requested (supersedes auto-detection).
if
(
isset
(
$this
->
params
[
'serverVersion'
]))
{
return
$this
->
params
[
'serverVersion'
];
}
if
(
isset
(
$this
->
params
[
'primary'
])
&&
isset
(
$this
->
params
[
'primary'
][
'serverVersion'
]))
{
return
$this
->
params
[
'primary'
][
'serverVersion'
];
}
// If not connected, we need to connect now to determine the platform version.
if
(
$this
->
_conn
===
null
)
{
try
{
$this
->
connect
();
}
catch
(
Exception
$originalException
)
{
if
(!
isset
(
$this
->
params
[
'dbname'
]))
{
throw
$originalException
;
}
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/5707'
,
'Relying on a fallback connection used to determine the database platform while connecting'
.
' to a non-existing database is deprecated. Either use an existing database name in'
.
' connection parameters or omit the database name if the platform'
.
' and the server configuration allow that.'
,
);
// The database to connect to might not yet exist.
// Retry detection without database name connection parameter.
$params
=
$this
->
params
;
unset
(
$this
->
params
[
'dbname'
]);
try
{
$this
->
connect
();
}
catch
(
Exception
$fallbackException
)
{
// Either the platform does not support database-less connections
// or something else went wrong.
throw
$originalException
;
}
finally
{
$this
->
params
=
$params
;
}
$serverVersion
=
$this
->
getServerVersion
();
// Close "temporary" connection to allow connecting to the real database again.
$this
->
close
();
return
$serverVersion
;
}
}
return
$this
->
getServerVersion
();
}
/**
* Returns the database server version if the underlying driver supports it.
*
* @return string|null
*
* @throws Exception
*/
private
function
getServerVersion
()
{
$connection
=
$this
->
getWrappedConnection
();
// Automatic platform version detection.
if
(
$connection
instanceof
ServerInfoAwareConnection
)
{
try
{
return
$connection
->
getServerVersion
();
}
catch
(
Driver\Exception
$e
)
{
throw
$this
->
convertException
(
$e
);
}
}
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/4750'
,
'Not implementing the ServerInfoAwareConnection interface in %s is deprecated'
,
get_class
(
$connection
),
);
// Unable to detect platform version.
return
null
;
}
/**
* Returns the current auto-commit mode for this connection.
*
* @see setAutoCommit
*
* @return bool True if auto-commit mode is currently enabled for this connection, false otherwise.
*/
public
function
isAutoCommit
()
{
return
$this
->
autoCommit
===
true
;
}
/**
* Sets auto-commit mode for this connection.
*
* If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual
* transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either
* the method commit or the method rollback. By default, new connections are in auto-commit mode.
*
* NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is
* committed. If this method is called and the auto-commit mode is not changed, the call is a no-op.
*
* @see isAutoCommit
*
* @param bool $autoCommit True to enable auto-commit mode; false to disable it.
*
* @return void
*/
public
function
setAutoCommit
(
$autoCommit
)
{
$autoCommit
=
(
bool
)
$autoCommit
;
// Mode not changed, no-op.
if
(
$autoCommit
===
$this
->
autoCommit
)
{
return
;
}
$this
->
autoCommit
=
$autoCommit
;
// Commit all currently active transactions if any when switching auto-commit mode.
if
(
$this
->
_conn
===
null
||
$this
->
transactionNestingLevel
===
0
)
{
return
;
}
$this
->
commitAll
();
}
/**
* Prepares and executes an SQL query and returns the first row of the result
* as an associative array.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return array<string, mixed>|false False is returned if no rows are found.
*
* @throws Exception
*/
public
function
fetchAssociative
(
string
$query
,
array
$params
=
[],
array
$types
=
[])
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
fetchAssociative
();
}
/**
* Prepares and executes an SQL query and returns the first row of the result
* as a numerically indexed array.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return list<mixed>|false False is returned if no rows are found.
*
* @throws Exception
*/
public
function
fetchNumeric
(
string
$query
,
array
$params
=
[],
array
$types
=
[])
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
fetchNumeric
();
}
/**
* Prepares and executes an SQL query and returns the value of a single column
* of the first row of the result.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return mixed|false False is returned if no rows are found.
*
* @throws Exception
*/
public
function
fetchOne
(
string
$query
,
array
$params
=
[],
array
$types
=
[])
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
fetchOne
();
}
/**
* Whether an actual connection to the database is established.
*
* @return bool
*/
public
function
isConnected
()
{
return
$this
->
_conn
!==
null
;
}
/**
* Checks whether a transaction is currently active.
*
* @return bool TRUE if a transaction is currently active, FALSE otherwise.
*/
public
function
isTransactionActive
()
{
return
$this
->
transactionNestingLevel
>
0
;
}
/**
* Adds condition based on the criteria to the query components
*
* @param array<string,mixed> $criteria Map of key columns to their values
* @param string[] $columns Column names
* @param mixed[] $values Column values
* @param string[] $conditions Key conditions
*
* @throws Exception
*/
private
function
addCriteriaCondition
(
array
$criteria
,
array
&
$columns
,
array
&
$values
,
array
&
$conditions
):
void
{
$platform
=
$this
->
getDatabasePlatform
();
foreach
(
$criteria
as
$columnName
=>
$value
)
{
if
(
$value
===
null
)
{
$conditions
[]
=
$platform
->
getIsNullExpression
(
$columnName
);
continue
;
}
$columns
[]
=
$columnName
;
$values
[]
=
$value
;
$conditions
[]
=
$columnName
.
' = ?'
;
}
}
/**
* Executes an SQL DELETE statement on a table.
*
* Table expression and columns are not escaped and are not safe for user-input.
*
* @param string $table Table name
* @param array<string, mixed> $criteria Deletion criteria
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return int|string The number of affected rows.
*
* @throws Exception
*/
public
function
delete
(
$table
,
array
$criteria
,
array
$types
=
[])
{
if
(
count
(
$criteria
)
===
0
)
{
throw
InvalidArgumentException
::
fromEmptyCriteria
();
}
$columns
=
$values
=
$conditions
=
[];
$this
->
addCriteriaCondition
(
$criteria
,
$columns
,
$values
,
$conditions
);
return
$this
->
executeStatement
(
'DELETE FROM '
.
$table
.
' WHERE '
.
implode
(
' AND '
,
$conditions
),
$values
,
is_string
(
key
(
$types
))
?
$this
->
extractTypeValues
(
$columns
,
$types
)
:
$types
,
);
}
/**
* Closes the connection.
*
* @return void
*/
public
function
close
()
{
$this
->
_conn
=
null
;
$this
->
transactionNestingLevel
=
0
;
}
/**
* Sets the transaction isolation level.
*
* @param TransactionIsolationLevel::* $level The level to set.
*
* @return int|string
*
* @throws Exception
*/
public
function
setTransactionIsolation
(
$level
)
{
$this
->
transactionIsolationLevel
=
$level
;
return
$this
->
executeStatement
(
$this
->
getDatabasePlatform
()->
getSetTransactionIsolationSQL
(
$level
));
}
/**
* Gets the currently active transaction isolation level.
*
* @return TransactionIsolationLevel::* The current transaction isolation level.
*
* @throws Exception
*/
public
function
getTransactionIsolation
()
{
return
$this
->
transactionIsolationLevel
??=
$this
->
getDatabasePlatform
()->
getDefaultTransactionIsolationLevel
();
}
/**
* Executes an SQL UPDATE statement on a table.
*
* Table expression and columns are not escaped and are not safe for user-input.
*
* @param string $table Table name
* @param array<string, mixed> $data Column-value pairs
* @param array<string, mixed> $criteria Update criteria
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return int|string The number of affected rows.
*
* @throws Exception
*/
public
function
update
(
$table
,
array
$data
,
array
$criteria
,
array
$types
=
[])
{
$columns
=
$values
=
$conditions
=
$set
=
[];
foreach
(
$data
as
$columnName
=>
$value
)
{
$columns
[]
=
$columnName
;
$values
[]
=
$value
;
$set
[]
=
$columnName
.
' = ?'
;
}
$this
->
addCriteriaCondition
(
$criteria
,
$columns
,
$values
,
$conditions
);
if
(
is_string
(
key
(
$types
)))
{
$types
=
$this
->
extractTypeValues
(
$columns
,
$types
);
}
$sql
=
'UPDATE '
.
$table
.
' SET '
.
implode
(
', '
,
$set
)
.
' WHERE '
.
implode
(
' AND '
,
$conditions
);
return
$this
->
executeStatement
(
$sql
,
$values
,
$types
);
}
/**
* Inserts a table row with specified data.
*
* Table expression and columns are not escaped and are not safe for user-input.
*
* @param string $table Table name
* @param array<string, mixed> $data Column-value pairs
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return int|string The number of affected rows.
*
* @throws Exception
*/
public
function
insert
(
$table
,
array
$data
,
array
$types
=
[])
{
if
(
count
(
$data
)
===
0
)
{
return
$this
->
executeStatement
(
'INSERT INTO '
.
$table
.
' () VALUES ()'
);
}
$columns
=
[];
$values
=
[];
$set
=
[];
foreach
(
$data
as
$columnName
=>
$value
)
{
$columns
[]
=
$columnName
;
$values
[]
=
$value
;
$set
[]
=
'?'
;
}
return
$this
->
executeStatement
(
'INSERT INTO '
.
$table
.
' ('
.
implode
(
', '
,
$columns
)
.
')'
.
' VALUES ('
.
implode
(
', '
,
$set
)
.
')'
,
$values
,
is_string
(
key
(
$types
))
?
$this
->
extractTypeValues
(
$columns
,
$types
)
:
$types
,
);
}
/**
* Extract ordered type list from an ordered column list and type map.
*
* @param array<int, string> $columnList
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types
*
* @return array<int, int|string|Type|null>|array<string, int|string|Type|null>
*/
private
function
extractTypeValues
(
array
$columnList
,
array
$types
):
array
{
$typeValues
=
[];
foreach
(
$columnList
as
$columnName
)
{
$typeValues
[]
=
$types
[
$columnName
]
??
ParameterType
::
STRING
;
}
return
$typeValues
;
}
/**
* Quotes a string so it can be safely used as a table or column name, even if
* it is a reserved name.
*
* Delimiting style depends on the underlying database platform that is being used.
*
* NOTE: Just because you CAN use quoted identifiers does not mean
* you SHOULD use them. In general, they end up causing way more
* problems than they solve.
*
* @param string $str The name to be quoted.
*
* @return string The quoted name.
*/
public
function
quoteIdentifier
(
$str
)
{
return
$this
->
getDatabasePlatform
()->
quoteIdentifier
(
$str
);
}
/**
* The usage of this method is discouraged. Use prepared statements
* or {@see AbstractPlatform::quoteStringLiteral()} instead.
*
* @param mixed $value
* @param int|string|Type|null $type
*
* @return mixed
*/
public
function
quote
(
$value
,
$type
=
ParameterType
::
STRING
)
{
$connection
=
$this
->
getWrappedConnection
();
[
$value
,
$bindingType
]
=
$this
->
getBindingInfo
(
$value
,
$type
);
return
$connection
->
quote
(
$value
,
$bindingType
);
}
/**
* Prepares and executes an SQL query and returns the result as an array of numeric arrays.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return list<list<mixed>>
*
* @throws Exception
*/
public
function
fetchAllNumeric
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
array
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
fetchAllNumeric
();
}
/**
* Prepares and executes an SQL query and returns the result as an array of associative arrays.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return list<array<string,mixed>>
*
* @throws Exception
*/
public
function
fetchAllAssociative
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
array
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
fetchAllAssociative
();
}
/**
* Prepares and executes an SQL query and returns the result as an associative array with the keys
* mapped to the first column and the values mapped to the second column.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return array<mixed,mixed>
*
* @throws Exception
*/
public
function
fetchAllKeyValue
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
array
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
fetchAllKeyValue
();
}
/**
* Prepares and executes an SQL query and returns the result as an associative array with the keys mapped
* to the first column and the values being an associative array representing the rest of the columns
* and their values.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return array<mixed,array<string,mixed>>
*
* @throws Exception
*/
public
function
fetchAllAssociativeIndexed
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
array
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
fetchAllAssociativeIndexed
();
}
/**
* Prepares and executes an SQL query and returns the result as an array of the first column values.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return list<mixed>
*
* @throws Exception
*/
public
function
fetchFirstColumn
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
array
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
fetchFirstColumn
();
}
/**
* Prepares and executes an SQL query and returns the result as an iterator over rows represented as numeric arrays.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return Traversable<int,list<mixed>>
*
* @throws Exception
*/
public
function
iterateNumeric
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
Traversable
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
iterateNumeric
();
}
/**
* Prepares and executes an SQL query and returns the result as an iterator over rows represented
* as associative arrays.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return Traversable<int,array<string,mixed>>
*
* @throws Exception
*/
public
function
iterateAssociative
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
Traversable
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
iterateAssociative
();
}
/**
* Prepares and executes an SQL query and returns the result as an iterator with the keys
* mapped to the first column and the values mapped to the second column.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return Traversable<mixed,mixed>
*
* @throws Exception
*/
public
function
iterateKeyValue
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
Traversable
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
iterateKeyValue
();
}
/**
* Prepares and executes an SQL query and returns the result as an iterator with the keys mapped
* to the first column and the values being an associative array representing the rest of the columns
* and their values.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string>|array<string, int|string> $types Parameter types
*
* @return Traversable<mixed,array<string,mixed>>
*
* @throws Exception
*/
public
function
iterateAssociativeIndexed
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
Traversable
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
iterateAssociativeIndexed
();
}
/**
* Prepares and executes an SQL query and returns the result as an iterator over the first column values.
*
* @param string $query SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return Traversable<int,mixed>
*
* @throws Exception
*/
public
function
iterateColumn
(
string
$query
,
array
$params
=
[],
array
$types
=
[]):
Traversable
{
return
$this
->
executeQuery
(
$query
,
$params
,
$types
)->
iterateColumn
();
}
/**
* Prepares an SQL statement.
*
* @param string $sql The SQL statement to prepare.
*
* @throws Exception
*/
public
function
prepare
(
string
$sql
):
Statement
{
$connection
=
$this
->
getWrappedConnection
();
try
{
$statement
=
$connection
->
prepare
(
$sql
);
}
catch
(
Driver\Exception
$e
)
{
throw
$this
->
convertExceptionDuringQuery
(
$e
,
$sql
);
}
return
new
Statement
(
$this
,
$statement
,
$sql
);
}
/**
* Executes an, optionally parameterized, SQL query.
*
* If the query is parametrized, a prepared statement is used.
* If an SQLLogger is configured, the execution is logged.
*
* @param string $sql SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @throws Exception
*/
public
function
executeQuery
(
string
$sql
,
array
$params
=
[],
$types
=
[],
?
QueryCacheProfile
$qcp
=
null
):
Result
{
if
(
$qcp
!==
null
)
{
return
$this
->
executeCacheQuery
(
$sql
,
$params
,
$types
,
$qcp
);
}
$connection
=
$this
->
getWrappedConnection
();
$logger
=
$this
->
_config
->
getSQLLogger
();
if
(
$logger
!==
null
)
{
$logger
->
startQuery
(
$sql
,
$params
,
$types
);
}
try
{
if
(
count
(
$params
)
>
0
)
{
if
(
$this
->
needsArrayParameterConversion
(
$params
,
$types
))
{
[
$sql
,
$params
,
$types
]
=
$this
->
expandArrayParameters
(
$sql
,
$params
,
$types
);
}
$stmt
=
$connection
->
prepare
(
$sql
);
$this
->
bindParameters
(
$stmt
,
$params
,
$types
);
$result
=
$stmt
->
execute
();
}
else
{
$result
=
$connection
->
query
(
$sql
);
}
return
new
Result
(
$result
,
$this
);
}
catch
(
Driver\Exception
$e
)
{
throw
$this
->
convertExceptionDuringQuery
(
$e
,
$sql
,
$params
,
$types
);
}
finally
{
if
(
$logger
!==
null
)
{
$logger
->
stopQuery
();
}
}
}
/**
* Executes a caching query.
*
* @param string $sql SQL query
* @param list<mixed>|array<string, mixed> $params Query parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @throws CacheException
* @throws Exception
*/
public
function
executeCacheQuery
(
$sql
,
$params
,
$types
,
QueryCacheProfile
$qcp
):
Result
{
$resultCache
=
$qcp
->
getResultCache
()
??
$this
->
_config
->
getResultCache
();
if
(
$resultCache
===
null
)
{
throw
CacheException
::
noResultDriverConfigured
();
}
$connectionParams
=
$this
->
params
;
unset
(
$connectionParams
[
'platform'
],
$connectionParams
[
'password'
],
$connectionParams
[
'url'
]);
[
$cacheKey
,
$realKey
]
=
$qcp
->
generateCacheKeys
(
$sql
,
$params
,
$types
,
$connectionParams
);
$item
=
$resultCache
->
getItem
(
$cacheKey
);
if
(
$item
->
isHit
())
{
$value
=
$item
->
get
();
if
(!
is_array
(
$value
))
{
$value
=
[];
}
if
(
isset
(
$value
[
$realKey
]))
{
return
new
Result
(
new
ArrayResult
(
$value
[
$realKey
]),
$this
);
}
}
else
{
$value
=
[];
}
$data
=
$this
->
fetchAllAssociative
(
$sql
,
$params
,
$types
);
$value
[
$realKey
]
=
$data
;
$item
->
set
(
$value
);
$lifetime
=
$qcp
->
getLifetime
();
if
(
$lifetime
>
0
)
{
$item
->
expiresAfter
(
$lifetime
);
}
$resultCache
->
save
(
$item
);
return
new
Result
(
new
ArrayResult
(
$data
),
$this
);
}
/**
* Executes an SQL statement with the given parameters and returns the number of affected rows.
*
* Could be used for:
* - DML statements: INSERT, UPDATE, DELETE, etc.
* - DDL statements: CREATE, DROP, ALTER, etc.
* - DCL statements: GRANT, REVOKE, etc.
* - Session control statements: ALTER SESSION, SET, DECLARE, etc.
* - Other statements that don't yield a row set.
*
* This method supports PDO binding types as well as DBAL mapping types.
*
* @param string $sql SQL statement
* @param list<mixed>|array<string, mixed> $params Statement parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @return int|string The number of affected rows.
*
* @throws Exception
*/
public
function
executeStatement
(
$sql
,
array
$params
=
[],
array
$types
=
[])
{
$connection
=
$this
->
getWrappedConnection
();
$logger
=
$this
->
_config
->
getSQLLogger
();
if
(
$logger
!==
null
)
{
$logger
->
startQuery
(
$sql
,
$params
,
$types
);
}
try
{
if
(
count
(
$params
)
>
0
)
{
if
(
$this
->
needsArrayParameterConversion
(
$params
,
$types
))
{
[
$sql
,
$params
,
$types
]
=
$this
->
expandArrayParameters
(
$sql
,
$params
,
$types
);
}
$stmt
=
$connection
->
prepare
(
$sql
);
$this
->
bindParameters
(
$stmt
,
$params
,
$types
);
return
$stmt
->
execute
()
->
rowCount
();
}
return
$connection
->
exec
(
$sql
);
}
catch
(
Driver\Exception
$e
)
{
throw
$this
->
convertExceptionDuringQuery
(
$e
,
$sql
,
$params
,
$types
);
}
finally
{
if
(
$logger
!==
null
)
{
$logger
->
stopQuery
();
}
}
}
/**
* Returns the current transaction nesting level.
*
* @return int The nesting level. A value of 0 means there's no active transaction.
*/
public
function
getTransactionNestingLevel
()
{
return
$this
->
transactionNestingLevel
;
}
/**
* Returns the ID of the last inserted row, or the last value from a sequence object,
* depending on the underlying driver.
*
* Note: This method may not return a meaningful or consistent result across different drivers,
* because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY
* columns or sequences.
*
* @param string|null $name Name of the sequence object from which the ID should be returned.
*
* @return string|int|false A string representation of the last inserted ID.
*
* @throws Exception
*/
public
function
lastInsertId
(
$name
=
null
)
{
if
(
$name
!==
null
)
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/4687'
,
'The usage of Connection::lastInsertId() with a sequence name is deprecated.'
,
);
}
try
{
return
$this
->
getWrappedConnection
()->
lastInsertId
(
$name
);
}
catch
(
Driver\Exception
$e
)
{
throw
$this
->
convertException
(
$e
);
}
}
/**
* Executes a function in a transaction.
*
* The function gets passed this Connection instance as an (optional) parameter.
*
* If an exception occurs during execution of the function or transaction commit,
* the transaction is rolled back and the exception re-thrown.
*
* @param Closure(self):T $func The function to execute transactionally.
*
* @return T The value returned by $func
*
* @throws Throwable
*
* @template T
*/
public
function
transactional
(
Closure
$func
)
{
$this
->
beginTransaction
();
try
{
$res
=
$func
(
$this
);
$this
->
commit
();
return
$res
;
}
catch
(
Throwable
$e
)
{
$this
->
rollBack
();
throw
$e
;
}
}
/**
* Sets if nested transactions should use savepoints.
*
* @param bool $nestTransactionsWithSavepoints
*
* @return void
*
* @throws Exception
*/
public
function
setNestTransactionsWithSavepoints
(
$nestTransactionsWithSavepoints
)
{
if
(!
$nestTransactionsWithSavepoints
)
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/5383'
,
<<<
'DEPRECATION'
Nesting
transactions
without
enabling
savepoints
is
deprecated
.
Call
%
s
::
setNestTransactionsWithSavepoints
(
true
)
to
enable
savepoints
.
DEPRECATION
,
self
::
class
,
);
}
if
(
$this
->
transactionNestingLevel
>
0
)
{
throw
ConnectionException
::
mayNotAlterNestedTransactionWithSavepointsInTransaction
();
}
$this
->
nestTransactionsWithSavepoints
=
(
bool
)
$nestTransactionsWithSavepoints
;
}
/**
* Gets if nested transactions should use savepoints.
*
* @return bool
*/
public
function
getNestTransactionsWithSavepoints
()
{
return
$this
->
nestTransactionsWithSavepoints
;
}
/**
* Returns the savepoint name to use for nested transactions.
*
* @return string
*/
protected
function
_getNestedTransactionSavePointName
()
{
return
'DOCTRINE_'
.
$this
->
transactionNestingLevel
;
}
/**
* @return bool
*
* @throws Exception
*/
public
function
beginTransaction
()
{
$connection
=
$this
->
getWrappedConnection
();
++
$this
->
transactionNestingLevel
;
$logger
=
$this
->
_config
->
getSQLLogger
();
if
(
$this
->
transactionNestingLevel
===
1
)
{
if
(
$logger
!==
null
)
{
$logger
->
startQuery
(
'"START TRANSACTION"'
);
}
$connection
->
beginTransaction
();
if
(
$logger
!==
null
)
{
$logger
->
stopQuery
();
}
}
elseif
(
$this
->
nestTransactionsWithSavepoints
)
{
if
(
$logger
!==
null
)
{
$logger
->
startQuery
(
'"SAVEPOINT"'
);
}
$this
->
createSavepoint
(
$this
->
_getNestedTransactionSavePointName
());
if
(
$logger
!==
null
)
{
$logger
->
stopQuery
();
}
}
else
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/5383'
,
<<<
'DEPRECATION'
Nesting
transactions
without
enabling
savepoints
is
deprecated
.
Call
%
s
::
setNestTransactionsWithSavepoints
(
true
)
to
enable
savepoints
.
DEPRECATION
,
self
::
class
,
);
}
$eventManager
=
$this
->
getEventManager
();
if
(
$eventManager
->
hasListeners
(
Events
::
onTransactionBegin
))
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/5784'
,
'Subscribing to %s events is deprecated.'
,
Events
::
onTransactionBegin
,
);
$eventManager
->
dispatchEvent
(
Events
::
onTransactionBegin
,
new
TransactionBeginEventArgs
(
$this
));
}
return
true
;
}
/**
* @return bool
*
* @throws Exception
*/
public
function
commit
()
{
if
(
$this
->
transactionNestingLevel
===
0
)
{
throw
ConnectionException
::
noActiveTransaction
();
}
if
(
$this
->
isRollbackOnly
)
{
throw
ConnectionException
::
commitFailedRollbackOnly
();
}
$result
=
true
;
$connection
=
$this
->
getWrappedConnection
();
if
(
$this
->
transactionNestingLevel
===
1
)
{
$result
=
$this
->
doCommit
(
$connection
);
}
elseif
(
$this
->
nestTransactionsWithSavepoints
)
{
$this
->
releaseSavepoint
(
$this
->
_getNestedTransactionSavePointName
());
}
--
$this
->
transactionNestingLevel
;
$eventManager
=
$this
->
getEventManager
();
if
(
$eventManager
->
hasListeners
(
Events
::
onTransactionCommit
))
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/5784'
,
'Subscribing to %s events is deprecated.'
,
Events
::
onTransactionCommit
,
);
$eventManager
->
dispatchEvent
(
Events
::
onTransactionCommit
,
new
TransactionCommitEventArgs
(
$this
));
}
if
(
$this
->
autoCommit
!==
false
||
$this
->
transactionNestingLevel
!==
0
)
{
return
$result
;
}
$this
->
beginTransaction
();
return
$result
;
}
/**
* @return bool
*
* @throws DriverException
*/
private
function
doCommit
(
DriverConnection
$connection
)
{
$logger
=
$this
->
_config
->
getSQLLogger
();
if
(
$logger
!==
null
)
{
$logger
->
startQuery
(
'"COMMIT"'
);
}
$result
=
$connection
->
commit
();
if
(
$logger
!==
null
)
{
$logger
->
stopQuery
();
}
return
$result
;
}
/**
* Commits all current nesting transactions.
*
* @throws Exception
*/
private
function
commitAll
():
void
{
while
(
$this
->
transactionNestingLevel
!==
0
)
{
if
(
$this
->
autoCommit
===
false
&&
$this
->
transactionNestingLevel
===
1
)
{
// When in no auto-commit mode, the last nesting commit immediately starts a new transaction.
// Therefore we need to do the final commit here and then leave to avoid an infinite loop.
$this
->
commit
();
return
;
}
$this
->
commit
();
}
}
/**
* Cancels any database changes done during the current transaction.
*
* @return bool
*
* @throws Exception
*/
public
function
rollBack
()
{
if
(
$this
->
transactionNestingLevel
===
0
)
{
throw
ConnectionException
::
noActiveTransaction
();
}
$connection
=
$this
->
getWrappedConnection
();
$logger
=
$this
->
_config
->
getSQLLogger
();
if
(
$this
->
transactionNestingLevel
===
1
)
{
if
(
$logger
!==
null
)
{
$logger
->
startQuery
(
'"ROLLBACK"'
);
}
$this
->
transactionNestingLevel
=
0
;
$connection
->
rollBack
();
$this
->
isRollbackOnly
=
false
;
if
(
$logger
!==
null
)
{
$logger
->
stopQuery
();
}
if
(
$this
->
autoCommit
===
false
)
{
$this
->
beginTransaction
();
}
}
elseif
(
$this
->
nestTransactionsWithSavepoints
)
{
if
(
$logger
!==
null
)
{
$logger
->
startQuery
(
'"ROLLBACK TO SAVEPOINT"'
);
}
$this
->
rollbackSavepoint
(
$this
->
_getNestedTransactionSavePointName
());
--
$this
->
transactionNestingLevel
;
if
(
$logger
!==
null
)
{
$logger
->
stopQuery
();
}
}
else
{
$this
->
isRollbackOnly
=
true
;
--
$this
->
transactionNestingLevel
;
}
$eventManager
=
$this
->
getEventManager
();
if
(
$eventManager
->
hasListeners
(
Events
::
onTransactionRollBack
))
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/5784'
,
'Subscribing to %s events is deprecated.'
,
Events
::
onTransactionRollBack
,
);
$eventManager
->
dispatchEvent
(
Events
::
onTransactionRollBack
,
new
TransactionRollBackEventArgs
(
$this
));
}
return
true
;
}
/**
* Creates a new savepoint.
*
* @param string $savepoint The name of the savepoint to create.
*
* @return void
*
* @throws Exception
*/
public
function
createSavepoint
(
$savepoint
)
{
$platform
=
$this
->
getDatabasePlatform
();
if
(!
$platform
->
supportsSavepoints
())
{
throw
ConnectionException
::
savepointsNotSupported
();
}
$this
->
executeStatement
(
$platform
->
createSavePoint
(
$savepoint
));
}
/**
* Releases the given savepoint.
*
* @param string $savepoint The name of the savepoint to release.
*
* @return void
*
* @throws Exception
*/
public
function
releaseSavepoint
(
$savepoint
)
{
$logger
=
$this
->
_config
->
getSQLLogger
();
$platform
=
$this
->
getDatabasePlatform
();
if
(!
$platform
->
supportsSavepoints
())
{
throw
ConnectionException
::
savepointsNotSupported
();
}
if
(!
$platform
->
supportsReleaseSavepoints
())
{
if
(
$logger
!==
null
)
{
$logger
->
stopQuery
();
}
return
;
}
if
(
$logger
!==
null
)
{
$logger
->
startQuery
(
'"RELEASE SAVEPOINT"'
);
}
$this
->
executeStatement
(
$platform
->
releaseSavePoint
(
$savepoint
));
if
(
$logger
===
null
)
{
return
;
}
$logger
->
stopQuery
();
}
/**
* Rolls back to the given savepoint.
*
* @param string $savepoint The name of the savepoint to rollback to.
*
* @return void
*
* @throws Exception
*/
public
function
rollbackSavepoint
(
$savepoint
)
{
$platform
=
$this
->
getDatabasePlatform
();
if
(!
$platform
->
supportsSavepoints
())
{
throw
ConnectionException
::
savepointsNotSupported
();
}
$this
->
executeStatement
(
$platform
->
rollbackSavePoint
(
$savepoint
));
}
/**
* Gets the wrapped driver connection.
*
* @deprecated Use {@link getNativeConnection()} to access the native connection.
*
* @return DriverConnection
*
* @throws Exception
*/
public
function
getWrappedConnection
()
{
Deprecation
::
triggerIfCalledFromOutside
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/4966'
,
'Connection::getWrappedConnection() is deprecated.'
.
' Use Connection::getNativeConnection() to access the native connection.'
,
);
$this
->
connect
();
return
$this
->
_conn
;
}
/** @return resource|object */
public
function
getNativeConnection
()
{
$this
->
connect
();
if
(!
method_exists
(
$this
->
_conn
,
'getNativeConnection'
))
{
throw
new
LogicException
(
sprintf
(
'The driver connection %s does not support accessing the native connection.'
,
get_class
(
$this
->
_conn
),
));
}
return
$this
->
_conn
->
getNativeConnection
();
}
/**
* Creates a SchemaManager that can be used to inspect or change the
* database schema through the connection.
*
* @throws Exception
*/
public
function
createSchemaManager
():
AbstractSchemaManager
{
return
$this
->
schemaManagerFactory
->
createSchemaManager
(
$this
);
}
/**
* Gets the SchemaManager that can be used to inspect or change the
* database schema through the connection.
*
* @deprecated Use {@see createSchemaManager()} instead.
*
* @return AbstractSchemaManager
*
* @throws Exception
*/
public
function
getSchemaManager
()
{
Deprecation
::
triggerIfCalledFromOutside
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/issues/4515'
,
'Connection::getSchemaManager() is deprecated, use Connection::createSchemaManager() instead.'
,
);
return
$this
->
_schemaManager
??=
$this
->
createSchemaManager
();
}
/**
* Marks the current transaction so that the only possible
* outcome for the transaction to be rolled back.
*
* @return void
*
* @throws ConnectionException If no transaction is active.
*/
public
function
setRollbackOnly
()
{
if
(
$this
->
transactionNestingLevel
===
0
)
{
throw
ConnectionException
::
noActiveTransaction
();
}
$this
->
isRollbackOnly
=
true
;
}
/**
* Checks whether the current transaction is marked for rollback only.
*
* @return bool
*
* @throws ConnectionException If no transaction is active.
*/
public
function
isRollbackOnly
()
{
if
(
$this
->
transactionNestingLevel
===
0
)
{
throw
ConnectionException
::
noActiveTransaction
();
}
return
$this
->
isRollbackOnly
;
}
/**
* Converts a given value to its database representation according to the conversion
* rules of a specific DBAL mapping type.
*
* @param mixed $value The value to convert.
* @param string $type The name of the DBAL mapping type.
*
* @return mixed The converted value.
*
* @throws Exception
*/
public
function
convertToDatabaseValue
(
$value
,
$type
)
{
return
Type
::
getType
(
$type
)->
convertToDatabaseValue
(
$value
,
$this
->
getDatabasePlatform
());
}
/**
* Converts a given value to its PHP representation according to the conversion
* rules of a specific DBAL mapping type.
*
* @param mixed $value The value to convert.
* @param string $type The name of the DBAL mapping type.
*
* @return mixed The converted type.
*
* @throws Exception
*/
public
function
convertToPHPValue
(
$value
,
$type
)
{
return
Type
::
getType
(
$type
)->
convertToPHPValue
(
$value
,
$this
->
getDatabasePlatform
());
}
/**
* Binds a set of parameters, some or all of which are typed with a PDO binding type
* or DBAL mapping type, to a given statement.
*
* @param DriverStatement $stmt Prepared statement
* @param list<mixed>|array<string, mixed> $params Statement parameters
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types Parameter types
*
* @throws Exception
*/
private
function
bindParameters
(
DriverStatement
$stmt
,
array
$params
,
array
$types
):
void
{
// Check whether parameters are positional or named. Mixing is not allowed.
if
(
is_int
(
key
(
$params
)))
{
$bindIndex
=
1
;
foreach
(
$params
as
$key
=>
$value
)
{
if
(
isset
(
$types
[
$key
]))
{
$type
=
$types
[
$key
];
[
$value
,
$bindingType
]
=
$this
->
getBindingInfo
(
$value
,
$type
);
}
else
{
if
(
array_key_exists
(
$key
,
$types
))
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/5550'
,
'Using NULL as prepared statement parameter type is deprecated.'
.
'Omit or use ParameterType::STRING instead'
,
);
}
$bindingType
=
ParameterType
::
STRING
;
}
$stmt
->
bindValue
(
$bindIndex
,
$value
,
$bindingType
);
++
$bindIndex
;
}
}
else
{
// Named parameters
foreach
(
$params
as
$name
=>
$value
)
{
if
(
isset
(
$types
[
$name
]))
{
$type
=
$types
[
$name
];
[
$value
,
$bindingType
]
=
$this
->
getBindingInfo
(
$value
,
$type
);
}
else
{
if
(
array_key_exists
(
$name
,
$types
))
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/5550'
,
'Using NULL as prepared statement parameter type is deprecated.'
.
'Omit or use ParameterType::STRING instead'
,
);
}
$bindingType
=
ParameterType
::
STRING
;
}
$stmt
->
bindValue
(
$name
,
$value
,
$bindingType
);
}
}
}
/**
* Gets the binding type of a given type.
*
* @param mixed $value The value to bind.
* @param int|string|Type|null $type The type to bind (PDO or DBAL).
*
* @return array{mixed, int} [0] => the (escaped) value, [1] => the binding type.
*
* @throws Exception
*/
private
function
getBindingInfo
(
$value
,
$type
):
array
{
if
(
is_string
(
$type
))
{
$type
=
Type
::
getType
(
$type
);
}
if
(
$type
instanceof
Type
)
{
$value
=
$type
->
convertToDatabaseValue
(
$value
,
$this
->
getDatabasePlatform
());
$bindingType
=
$type
->
getBindingType
();
}
else
{
$bindingType
=
$type
??
ParameterType
::
STRING
;
}
return
[
$value
,
$bindingType
];
}
/**
* Creates a new instance of a SQL query builder.
*
* @return QueryBuilder
*/
public
function
createQueryBuilder
()
{
return
new
Query\QueryBuilder
(
$this
);
}
/**
* @internal
*
* @param list<mixed>|array<string, mixed> $params
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types
*/
final
public
function
convertExceptionDuringQuery
(
Driver\Exception
$e
,
string
$sql
,
array
$params
=
[],
array
$types
=
[]
):
DriverException
{
return
$this
->
handleDriverException
(
$e
,
new
Query
(
$sql
,
$params
,
$types
));
}
/** @internal */
final
public
function
convertException
(
Driver\Exception
$e
):
DriverException
{
return
$this
->
handleDriverException
(
$e
,
null
);
}
/**
* @param array<int, mixed>|array<string, mixed> $params
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types
*
* @return array{string, list<mixed>, array<int,Type|int|string|null>}
*/
private
function
expandArrayParameters
(
string
$sql
,
array
$params
,
array
$types
):
array
{
$this
->
parser
??=
$this
->
getDatabasePlatform
()->
createSQLParser
();
$visitor
=
new
ExpandArrayParameters
(
$params
,
$types
);
$this
->
parser
->
parse
(
$sql
,
$visitor
);
return
[
$visitor
->
getSQL
(),
$visitor
->
getParameters
(),
$visitor
->
getTypes
(),
];
}
/**
* @param array<int, mixed>|array<string, mixed> $params
* @param array<int, int|string|Type|null>|array<string, int|string|Type|null> $types
*/
private
function
needsArrayParameterConversion
(
array
$params
,
array
$types
):
bool
{
if
(
is_string
(
key
(
$params
)))
{
return
true
;
}
foreach
(
$types
as
$type
)
{
if
(
$type
===
ArrayParameterType
::
INTEGER
||
$type
===
ArrayParameterType
::
STRING
||
$type
===
ArrayParameterType
::
ASCII
||
$type
===
ArrayParameterType
::
BINARY
)
{
return
true
;
}
}
return
false
;
}
private
function
handleDriverException
(
Driver\Exception
$driverException
,
?
Query
$query
):
DriverException
{
$this
->
exceptionConverter
??=
$this
->
_driver
->
getExceptionConverter
();
$exception
=
$this
->
exceptionConverter
->
convert
(
$driverException
,
$query
);
if
(
$exception
instanceof
ConnectionLost
)
{
$this
->
close
();
}
return
$exception
;
}
/**
* BC layer for a wide-spread use-case of old DBAL APIs
*
* @deprecated Use {@see executeStatement()} instead
*
* @param array<mixed> $params The query parameters
* @param array<int|string|null> $types The parameter types
*/
public
function
executeUpdate
(
string
$sql
,
array
$params
=
[],
array
$types
=
[]):
int
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/4163'
,
'%s is deprecated, please use executeStatement() instead.'
,
__METHOD__
,
);
return
$this
->
executeStatement
(
$sql
,
$params
,
$types
);
}
/**
* BC layer for a wide-spread use-case of old DBAL APIs
*
* @deprecated Use {@see executeQuery()} instead
*/
public
function
query
(
string
$sql
):
Result
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/4163'
,
'%s is deprecated, please use executeQuery() instead.'
,
__METHOD__
,
);
return
$this
->
executeQuery
(
$sql
);
}
/**
* BC layer for a wide-spread use-case of old DBAL APIs
*
* @deprecated please use {@see executeStatement()} instead
*/
public
function
exec
(
string
$sql
):
int
{
Deprecation
::
trigger
(
'doctrine/dbal'
,
'https://github.com/doctrine/dbal/pull/4163'
,
'%s is deprecated, please use executeStatement() instead.'
,
__METHOD__
,
);
return
$this
->
executeStatement
(
$sql
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, May 16, 22:36 (2 h, 13 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
b6/c1/ad0ffc0597898198725966ff8c3b
Default Alt Text
Connection.php (63 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment