summaryrefslogtreecommitdiff
path: root/vendor/doctrine/dbal/src/Statement.php
blob: 9b4a3b43bca5abe0e3c1070a780805fabce225c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<?php

declare(strict_types=1);

namespace Doctrine\DBAL;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;

use function is_string;

/**
 * A database abstraction-level statement that implements support for logging, DBAL mapping types, etc.
 */
class Statement
{
    /**
     * The bound parameters.
     *
     * @var mixed[]
     */
    protected array $params = [];

    /**
     * The parameter types.
     *
     * @var ParameterType[]|string[]|Type[]
     */
    protected array $types = [];

    /**
     * The underlying database platform.
     */
    protected AbstractPlatform $platform;

    /**
     * Creates a new <tt>Statement</tt> for the given SQL and <tt>Connection</tt>.
     *
     * @internal The statement can be only instantiated by {@see Connection}.
     *
     * @param Connection       $conn The connection for handling statement errors.
     * @param Driver\Statement $stmt The underlying driver-level statement.
     * @param string           $sql  The SQL of the statement.
     *
     * @throws Exception
     */
    public function __construct(
        protected Connection $conn,
        protected Driver\Statement $stmt,
        protected string $sql,
    ) {
        $this->platform = $conn->getDatabasePlatform();
    }

    /**
     * Binds a parameter value to the statement.
     *
     * The value can optionally be bound with a DBAL mapping type.
     * If bound with a DBAL mapping type, the binding type is derived from the mapping
     * type and the value undergoes the conversion routines of the mapping type before
     * being bound.
     *
     * @param string|int                $param Parameter identifier. For a prepared statement using named placeholders,
     *                                         this will be a parameter name of the form :name. For a prepared statement
     *                                         using question mark placeholders, this will be the 1-indexed position
     *                                         of the parameter.
     * @param mixed                     $value The value to bind to the parameter.
     * @param ParameterType|string|Type $type  Either a {@see \Doctrine\DBAL\ParameterType} or a DBAL mapping type name
     *                                or instance.
     *
     * @throws Exception
     */
    public function bindValue(
        string|int $param,
        mixed $value,
        string|ParameterType|Type $type = ParameterType::STRING,
    ): void {
        $this->params[$param] = $value;
        $this->types[$param]  = $type;

        if (is_string($type)) {
            $type = Type::getType($type);
        }

        if ($type instanceof Type) {
            $value       = $type->convertToDatabaseValue($value, $this->platform);
            $bindingType = $type->getBindingType();
        } else {
            $bindingType = $type;
        }

        try {
            $this->stmt->bindValue($param, $value, $bindingType);
        } catch (Driver\Exception $e) {
            throw $this->conn->convertException($e);
        }
    }

    /** @throws Exception */
    private function execute(): Result
    {
        try {
            return new Result(
                $this->stmt->execute(),
                $this->conn,
            );
        } catch (Driver\Exception $ex) {
            throw $this->conn->convertExceptionDuringQuery($ex, $this->sql, $this->params, $this->types);
        }
    }

    /**
     * Executes the statement with the currently bound parameters and return result.
     *
     * @throws Exception
     */
    public function executeQuery(): Result
    {
        return $this->execute();
    }

    /**
     * Executes the statement with the currently bound parameters and return affected rows.
     *
     * If the number of rows exceeds {@see PHP_INT_MAX}, it might be returned as string if the driver supports it.
     *
     * @return int|numeric-string
     *
     * @throws Exception
     */
    public function executeStatement(): int|string
    {
        return $this->execute()->rowCount();
    }

    /**
     * Gets the wrapped driver statement.
     */
    public function getWrappedStatement(): Driver\Statement
    {
        return $this->stmt;
    }
}