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\IBMDB2;
4
 
5
use Doctrine\DBAL\Driver\Exception;
6
use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotCopyStreamToStream;
7
use Doctrine\DBAL\Driver\IBMDB2\Exception\CannotCreateTemporaryFile;
8
use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError;
9
use Doctrine\DBAL\Driver\Result as ResultInterface;
10
use Doctrine\DBAL\Driver\Statement as StatementInterface;
11
use Doctrine\DBAL\ParameterType;
12
use Doctrine\Deprecations\Deprecation;
13
 
14
use function assert;
15
use function db2_bind_param;
16
use function db2_execute;
17
use function error_get_last;
18
use function fclose;
19
use function func_num_args;
20
use function is_int;
21
use function is_resource;
22
use function stream_copy_to_stream;
23
use function stream_get_meta_data;
24
use function tmpfile;
25
 
26
use const DB2_BINARY;
27
use const DB2_CHAR;
28
use const DB2_LONG;
29
use const DB2_PARAM_FILE;
30
use const DB2_PARAM_IN;
31
 
32
final class Statement implements StatementInterface
33
{
34
    /** @var resource */
35
    private $stmt;
36
 
37
    /** @var mixed[] */
38
    private array $parameters = [];
39
 
40
    /**
41
     * Map of LOB parameter positions to the tuples containing reference to the variable bound to the driver statement
42
     * and the temporary file handle bound to the underlying statement
43
     *
44
     * @var array<int,string|resource|null>
45
     */
46
    private array $lobs = [];
47
 
48
    /**
49
     * @internal The statement can be only instantiated by its driver connection.
50
     *
51
     * @param resource $stmt
52
     */
53
    public function __construct($stmt)
54
    {
55
        $this->stmt = $stmt;
56
    }
57
 
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function bindValue($param, $value, $type = ParameterType::STRING): bool
62
    {
63
        assert(is_int($param));
64
 
65
        if (func_num_args() < 3) {
66
            Deprecation::trigger(
67
                'doctrine/dbal',
68
                'https://github.com/doctrine/dbal/pull/5558',
69
                'Not passing $type to Statement::bindValue() is deprecated.'
70
                    . ' Pass the type corresponding to the parameter being bound.',
71
            );
72
        }
73
 
74
        return $this->bindParam($param, $value, $type);
75
    }
76
 
77
    /**
78
     * {@inheritdoc}
79
     *
80
     * @deprecated Use {@see bindValue()} instead.
81
     */
82
    public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null): bool
83
    {
84
        Deprecation::trigger(
85
            'doctrine/dbal',
86
            'https://github.com/doctrine/dbal/pull/5563',
87
            '%s is deprecated. Use bindValue() instead.',
88
            __METHOD__,
89
        );
90
 
91
        assert(is_int($param));
92
 
93
        if (func_num_args() < 3) {
94
            Deprecation::trigger(
95
                'doctrine/dbal',
96
                'https://github.com/doctrine/dbal/pull/5558',
97
                'Not passing $type to Statement::bindParam() is deprecated.'
98
                    . ' Pass the type corresponding to the parameter being bound.',
99
            );
100
        }
101
 
102
        switch ($type) {
103
            case ParameterType::INTEGER:
104
                $this->bind($param, $variable, DB2_PARAM_IN, DB2_LONG);
105
                break;
106
 
107
            case ParameterType::LARGE_OBJECT:
108
                $this->lobs[$param] = &$variable;
109
                break;
110
 
111
            default:
112
                $this->bind($param, $variable, DB2_PARAM_IN, DB2_CHAR);
113
                break;
114
        }
115
 
116
        return true;
117
    }
118
 
119
    /**
120
     * @param int   $position Parameter position
121
     * @param mixed $variable
122
     *
123
     * @throws Exception
124
     */
125
    private function bind($position, &$variable, int $parameterType, int $dataType): void
126
    {
127
        $this->parameters[$position] =& $variable;
128
 
129
        if (! db2_bind_param($this->stmt, $position, '', $parameterType, $dataType)) {
130
            throw StatementError::new($this->stmt);
131
        }
132
    }
133
 
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function execute($params = null): ResultInterface
138
    {
139
        if ($params !== null) {
140
            Deprecation::trigger(
141
                'doctrine/dbal',
142
                'https://github.com/doctrine/dbal/pull/5556',
143
                'Passing $params to Statement::execute() is deprecated. Bind parameters using'
144
                    . ' Statement::bindParam() or Statement::bindValue() instead.',
145
            );
146
        }
147
 
148
        $handles = $this->bindLobs();
149
 
150
        $result = @db2_execute($this->stmt, $params ?? $this->parameters);
151
 
152
        foreach ($handles as $handle) {
153
            fclose($handle);
154
        }
155
 
156
        $this->lobs = [];
157
 
158
        if ($result === false) {
159
            throw StatementError::new($this->stmt);
160
        }
161
 
162
        return new Result($this->stmt);
163
    }
164
 
165
    /**
166
     * @return list<resource>
167
     *
168
     * @throws Exception
169
     */
170
    private function bindLobs(): array
171
    {
172
        $handles = [];
173
 
174
        foreach ($this->lobs as $param => $value) {
175
            if (is_resource($value)) {
176
                $handle = $handles[] = $this->createTemporaryFile();
177
                $path   = stream_get_meta_data($handle)['uri'];
178
 
179
                $this->copyStreamToStream($value, $handle);
180
 
181
                $this->bind($param, $path, DB2_PARAM_FILE, DB2_BINARY);
182
            } else {
183
                $this->bind($param, $value, DB2_PARAM_IN, DB2_CHAR);
184
            }
185
        }
186
 
187
        return $handles;
188
    }
189
 
190
    /**
191
     * @return resource
192
     *
193
     * @throws Exception
194
     */
195
    private function createTemporaryFile()
196
    {
197
        $handle = @tmpfile();
198
 
199
        if ($handle === false) {
200
            throw CannotCreateTemporaryFile::new(error_get_last());
201
        }
202
 
203
        return $handle;
204
    }
205
 
206
    /**
207
     * @param resource $source
208
     * @param resource $target
209
     *
210
     * @throws Exception
211
     */
212
    private function copyStreamToStream($source, $target): void
213
    {
214
        if (@stream_copy_to_stream($source, $target) === false) {
215
            throw CannotCopyStreamToStream::new(error_get_last());
216
        }
217
    }
218
}