1<?php
2
3namespace Doctrine\DBAL\Driver\IBMDB2;
4
5use Doctrine\DBAL\Driver\Connection;
6use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
7use Doctrine\DBAL\ParameterType;
8use stdClass;
9
10use function assert;
11use function db2_autocommit;
12use function db2_commit;
13use function db2_conn_error;
14use function db2_conn_errormsg;
15use function db2_connect;
16use function db2_escape_string;
17use function db2_exec;
18use function db2_last_insert_id;
19use function db2_num_rows;
20use function db2_pconnect;
21use function db2_prepare;
22use function db2_rollback;
23use function db2_server_info;
24use function db2_stmt_errormsg;
25use function func_get_args;
26use function is_bool;
27
28use const DB2_AUTOCOMMIT_OFF;
29use const DB2_AUTOCOMMIT_ON;
30
31class DB2Connection implements Connection, ServerInfoAwareConnection
32{
33    /** @var resource */
34    private $conn = null;
35
36    /**
37     * @param mixed[] $params
38     * @param string  $username
39     * @param string  $password
40     * @param mixed[] $driverOptions
41     *
42     * @throws DB2Exception
43     */
44    public function __construct(array $params, $username, $password, $driverOptions = [])
45    {
46        $isPersistent = (isset($params['persistent']) && $params['persistent'] === true);
47
48        if ($isPersistent) {
49            $conn = db2_pconnect($params['dbname'], $username, $password, $driverOptions);
50        } else {
51            $conn = db2_connect($params['dbname'], $username, $password, $driverOptions);
52        }
53
54        if ($conn === false) {
55            throw new DB2Exception(db2_conn_errormsg());
56        }
57
58        $this->conn = $conn;
59    }
60
61    /**
62     * {@inheritdoc}
63     */
64    public function getServerVersion()
65    {
66        $serverInfo = db2_server_info($this->conn);
67        assert($serverInfo instanceof stdClass);
68
69        return $serverInfo->DBMS_VER;
70    }
71
72    /**
73     * {@inheritdoc}
74     */
75    public function requiresQueryForServerVersion()
76    {
77        return false;
78    }
79
80    /**
81     * {@inheritdoc}
82     */
83    public function prepare($sql)
84    {
85        $stmt = @db2_prepare($this->conn, $sql);
86        if (! $stmt) {
87            throw new DB2Exception(db2_stmt_errormsg());
88        }
89
90        return new DB2Statement($stmt);
91    }
92
93    /**
94     * {@inheritdoc}
95     */
96    public function query()
97    {
98        $args = func_get_args();
99        $sql  = $args[0];
100        $stmt = $this->prepare($sql);
101        $stmt->execute();
102
103        return $stmt;
104    }
105
106    /**
107     * {@inheritdoc}
108     */
109    public function quote($value, $type = ParameterType::STRING)
110    {
111        $value = db2_escape_string($value);
112
113        if ($type === ParameterType::INTEGER) {
114            return $value;
115        }
116
117        return "'" . $value . "'";
118    }
119
120    /**
121     * {@inheritdoc}
122     */
123    public function exec($sql)
124    {
125        $stmt = @db2_exec($this->conn, $sql);
126
127        if ($stmt === false) {
128            throw new DB2Exception(db2_stmt_errormsg());
129        }
130
131        return db2_num_rows($stmt);
132    }
133
134    /**
135     * {@inheritdoc}
136     */
137    public function lastInsertId($name = null)
138    {
139        return db2_last_insert_id($this->conn);
140    }
141
142    /**
143     * {@inheritdoc}
144     */
145    public function beginTransaction()
146    {
147        $result = db2_autocommit($this->conn, DB2_AUTOCOMMIT_OFF);
148        assert(is_bool($result));
149
150        return $result;
151    }
152
153    /**
154     * {@inheritdoc}
155     */
156    public function commit()
157    {
158        if (! db2_commit($this->conn)) {
159            throw new DB2Exception(db2_conn_errormsg($this->conn));
160        }
161
162        $result = db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON);
163        assert(is_bool($result));
164
165        return $result;
166    }
167
168    /**
169     * {@inheritdoc}
170     */
171    public function rollBack()
172    {
173        if (! db2_rollback($this->conn)) {
174            throw new DB2Exception(db2_conn_errormsg($this->conn));
175        }
176
177        $result = db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON);
178        assert(is_bool($result));
179
180        return $result;
181    }
182
183    /**
184     * {@inheritdoc}
185     */
186    public function errorCode()
187    {
188        return db2_conn_error($this->conn);
189    }
190
191    /**
192     * {@inheritdoc}
193     */
194    public function errorInfo()
195    {
196        return [
197            0 => db2_conn_errormsg($this->conn),
198            1 => $this->errorCode(),
199        ];
200    }
201}
202