Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Doctrine\DBAL\Driver\SQLSrv;
4
 
5
use Doctrine\DBAL\Driver\Exception;
6
use Doctrine\DBAL\Driver\Result as ResultInterface;
7
use Doctrine\DBAL\Driver\SQLSrv\Exception\Error;
8
use Doctrine\DBAL\Driver\Statement as StatementInterface;
9
use Doctrine\DBAL\ParameterType;
10
use Doctrine\Deprecations\Deprecation;
11
 
12
use function assert;
13
use function func_num_args;
14
use function is_int;
15
use function sqlsrv_execute;
16
use function SQLSRV_PHPTYPE_STREAM;
17
use function SQLSRV_PHPTYPE_STRING;
18
use function sqlsrv_prepare;
19
use function SQLSRV_SQLTYPE_VARBINARY;
20
use function stripos;
21
 
22
use const SQLSRV_ENC_BINARY;
23
use const SQLSRV_ENC_CHAR;
24
use const SQLSRV_PARAM_IN;
25
 
26
final class Statement implements StatementInterface
27
{
28
    /**
29
     * The SQLSRV Resource.
30
     *
31
     * @var resource
32
     */
33
    private $conn;
34
 
35
    /**
36
     * The SQL statement to execute.
37
     */
38
    private string $sql;
39
 
40
    /**
41
     * The SQLSRV statement resource.
42
     *
43
     * @var resource|null
44
     */
45
    private $stmt;
46
 
47
    /**
48
     * References to the variables bound as statement parameters.
49
     *
50
     * @var array<int, mixed>
51
     */
52
    private array $variables = [];
53
 
54
    /**
55
     * Bound parameter types.
56
     *
57
     * @var array<int, int>
58
     */
59
    private array $types = [];
60
 
61
    /**
62
     * Append to any INSERT query to retrieve the last insert id.
63
     */
64
    private const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;';
65
 
66
    /**
67
     * @internal The statement can be only instantiated by its driver connection.
68
     *
69
     * @param resource $conn
70
     * @param string   $sql
71
     */
72
    public function __construct($conn, $sql)
73
    {
74
        $this->conn = $conn;
75
        $this->sql  = $sql;
76
 
77
        if (stripos($sql, 'INSERT INTO ') !== 0) {
78
            return;
79
        }
80
 
81
        $this->sql .= self::LAST_INSERT_ID_SQL;
82
    }
83
 
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function bindValue($param, $value, $type = ParameterType::STRING): bool
88
    {
89
        assert(is_int($param));
90
 
91
        if (func_num_args() < 3) {
92
            Deprecation::trigger(
93
                'doctrine/dbal',
94
                'https://github.com/doctrine/dbal/pull/5558',
95
                'Not passing $type to Statement::bindValue() is deprecated.'
96
                    . ' Pass the type corresponding to the parameter being bound.',
97
            );
98
        }
99
 
100
        $this->variables[$param] = $value;
101
        $this->types[$param]     = $type;
102
 
103
        return true;
104
    }
105
 
106
    /**
107
     * {@inheritdoc}
108
     *
109
     * @deprecated Use {@see bindValue()} instead.
110
     */
111
    public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null): bool
112
    {
113
        Deprecation::trigger(
114
            'doctrine/dbal',
115
            'https://github.com/doctrine/dbal/pull/5563',
116
            '%s is deprecated. Use bindValue() instead.',
117
            __METHOD__,
118
        );
119
 
120
        assert(is_int($param));
121
 
122
        if (func_num_args() < 3) {
123
            Deprecation::trigger(
124
                'doctrine/dbal',
125
                'https://github.com/doctrine/dbal/pull/5558',
126
                'Not passing $type to Statement::bindParam() is deprecated.'
127
                    . ' Pass the type corresponding to the parameter being bound.',
128
            );
129
        }
130
 
131
        $this->variables[$param] =& $variable;
132
        $this->types[$param]     = $type;
133
 
134
        // unset the statement resource if it exists as the new one will need to be bound to the new variable
135
        $this->stmt = null;
136
 
137
        return true;
138
    }
139
 
140
    /**
141
     * {@inheritdoc}
142
     */
143
    public function execute($params = null): ResultInterface
144
    {
145
        if ($params !== null) {
146
            Deprecation::trigger(
147
                'doctrine/dbal',
148
                'https://github.com/doctrine/dbal/pull/5556',
149
                'Passing $params to Statement::execute() is deprecated. Bind parameters using'
150
                    . ' Statement::bindParam() or Statement::bindValue() instead.',
151
            );
152
 
153
            foreach ($params as $key => $val) {
154
                if (is_int($key)) {
155
                    $this->bindValue($key + 1, $val, ParameterType::STRING);
156
                } else {
157
                    $this->bindValue($key, $val, ParameterType::STRING);
158
                }
159
            }
160
        }
161
 
162
        $this->stmt ??= $this->prepare();
163
 
164
        if (! sqlsrv_execute($this->stmt)) {
165
            throw Error::new();
166
        }
167
 
168
        return new Result($this->stmt);
169
    }
170
 
171
    /**
172
     * Prepares SQL Server statement resource
173
     *
174
     * @return resource
175
     *
176
     * @throws Exception
177
     */
178
    private function prepare()
179
    {
180
        $params = [];
181
 
182
        foreach ($this->variables as $column => &$variable) {
183
            switch ($this->types[$column]) {
184
                case ParameterType::LARGE_OBJECT:
185
                    $params[$column - 1] = [
186
                        &$variable,
187
                        SQLSRV_PARAM_IN,
188
                        SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY),
189
                        SQLSRV_SQLTYPE_VARBINARY('max'),
190
                    ];
191
                    break;
192
 
193
                case ParameterType::BINARY:
194
                    $params[$column - 1] = [
195
                        &$variable,
196
                        SQLSRV_PARAM_IN,
197
                        SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
198
                    ];
199
                    break;
200
 
201
                case ParameterType::ASCII:
202
                    $params[$column - 1] = [
203
                        &$variable,
204
                        SQLSRV_PARAM_IN,
205
                        SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
206
                    ];
207
                    break;
208
 
209
                default:
210
                    $params[$column - 1] =& $variable;
211
                    break;
212
            }
213
        }
214
 
215
        $stmt = sqlsrv_prepare($this->conn, $this->sql, $params);
216
 
217
        if ($stmt === false) {
218
            throw Error::new();
219
        }
220
 
221
        return $stmt;
222
    }
223
}