summaryrefslogtreecommitdiff
path: root/vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php')
-rw-r--r--vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php140
1 files changed, 140 insertions, 0 deletions
diff --git a/vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php b/vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php
new file mode 100644
index 0000000..dc7827a
--- /dev/null
+++ b/vendor/doctrine/dbal/src/Driver/SQLSrv/Statement.php
@@ -0,0 +1,140 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\DBAL\Driver\SQLSrv;
6
7use Doctrine\DBAL\Driver\Exception;
8use Doctrine\DBAL\Driver\SQLSrv\Exception\Error;
9use Doctrine\DBAL\Driver\Statement as StatementInterface;
10use Doctrine\DBAL\ParameterType;
11
12use function assert;
13use function is_int;
14use function sqlsrv_execute;
15use function SQLSRV_PHPTYPE_STREAM;
16use function SQLSRV_PHPTYPE_STRING;
17use function sqlsrv_prepare;
18use function SQLSRV_SQLTYPE_VARBINARY;
19use function stripos;
20
21use const SQLSRV_ENC_BINARY;
22use const SQLSRV_ENC_CHAR;
23use const SQLSRV_PARAM_IN;
24
25final class Statement implements StatementInterface
26{
27 /**
28 * The SQLSRV statement resource.
29 *
30 * @var resource|null
31 */
32 private $stmt;
33
34 /**
35 * References to the variables bound as statement parameters.
36 *
37 * @var array<int, mixed>
38 */
39 private array $variables = [];
40
41 /**
42 * Bound parameter types.
43 *
44 * @var array<int, ParameterType>
45 */
46 private array $types = [];
47
48 /**
49 * Append to any INSERT query to retrieve the last insert id.
50 */
51 private const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;';
52
53 /**
54 * @internal The statement can be only instantiated by its driver connection.
55 *
56 * @param resource $conn
57 */
58 public function __construct(
59 private readonly mixed $conn,
60 private string $sql,
61 ) {
62 if (stripos($sql, 'INSERT INTO ') !== 0) {
63 return;
64 }
65
66 $this->sql .= self::LAST_INSERT_ID_SQL;
67 }
68
69 public function bindValue(int|string $param, mixed $value, ParameterType $type): void
70 {
71 assert(is_int($param));
72
73 $this->variables[$param] = $value;
74 $this->types[$param] = $type;
75 }
76
77 public function execute(): Result
78 {
79 $this->stmt ??= $this->prepare();
80
81 if (! sqlsrv_execute($this->stmt)) {
82 throw Error::new();
83 }
84
85 return new Result($this->stmt);
86 }
87
88 /**
89 * Prepares SQL Server statement resource
90 *
91 * @return resource
92 *
93 * @throws Exception
94 */
95 private function prepare()
96 {
97 $params = [];
98
99 foreach ($this->variables as $column => &$variable) {
100 switch ($this->types[$column]) {
101 case ParameterType::LARGE_OBJECT:
102 $params[$column - 1] = [
103 &$variable,
104 SQLSRV_PARAM_IN,
105 SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY),
106 SQLSRV_SQLTYPE_VARBINARY('max'),
107 ];
108 break;
109
110 case ParameterType::BINARY:
111 $params[$column - 1] = [
112 &$variable,
113 SQLSRV_PARAM_IN,
114 SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
115 ];
116 break;
117
118 case ParameterType::ASCII:
119 $params[$column - 1] = [
120 &$variable,
121 SQLSRV_PARAM_IN,
122 SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
123 ];
124 break;
125
126 default:
127 $params[$column - 1] =& $variable;
128 break;
129 }
130 }
131
132 $stmt = sqlsrv_prepare($this->conn, $this->sql, $params);
133
134 if ($stmt === false) {
135 throw Error::new();
136 }
137
138 return $stmt;
139 }
140}