SQLAnywhereStatement.php 6.44 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\DBAL\Driver\SQLAnywhere;

5
use Doctrine\DBAL\Driver\Statement;
6
use Doctrine\DBAL\Driver\StatementIterator;
7 8
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
9
use IteratorAggregate;
10 11
use const SASQL_BOTH;
use function array_key_exists;
12
use function assert;
Sergei Morozov's avatar
Sergei Morozov committed
13
use function is_int;
14 15 16 17 18 19 20 21 22 23 24 25 26
use function is_resource;
use function sasql_fetch_array;
use function sasql_fetch_assoc;
use function sasql_fetch_row;
use function sasql_prepare;
use function sasql_stmt_affected_rows;
use function sasql_stmt_bind_param_ex;
use function sasql_stmt_errno;
use function sasql_stmt_error;
use function sasql_stmt_execute;
use function sasql_stmt_field_count;
use function sasql_stmt_reset;
use function sasql_stmt_result_metadata;
27 28 29 30 31 32

/**
 * SAP SQL Anywhere implementation of the Statement interface.
 */
class SQLAnywhereStatement implements IteratorAggregate, Statement
{
33
    /** @var resource The connection resource. */
34
    private $conn;
Steve Müller's avatar
Steve Müller committed
35

36
    /** @var int Default fetch mode to use. */
37
    private $defaultFetchMode = FetchMode::MIXED;
Steve Müller's avatar
Steve Müller committed
38

39
    /** @var resource|null The result set resource to fetch. */
40
    private $result;
Steve Müller's avatar
Steve Müller committed
41

42
    /** @var resource The prepared SQL statement to execute. */
43 44
    private $stmt;

45 46 47
    /** @var mixed[] The references to bound parameter values. */
    private $boundValues = [];

48 49 50 51 52 53 54 55 56 57
    /**
     * Prepares given statement for given connection.
     *
     * @param resource $conn The connection resource to use.
     * @param string   $sql  The SQL statement to prepare.
     *
     * @throws SQLAnywhereException
     */
    public function __construct($conn, $sql)
    {
58
        if (! is_resource($conn)) {
59 60 61 62 63 64
            throw new SQLAnywhereException('Invalid SQL Anywhere connection resource: ' . $conn);
        }

        $this->conn = $conn;
        $this->stmt = sasql_prepare($conn, $sql);

65
        if (! is_resource($this->stmt)) {
66 67 68 69 70 71 72 73 74
            throw SQLAnywhereException::fromSQLAnywhereError($conn);
        }
    }

    /**
     * {@inheritdoc}
     *
     * @throws SQLAnywhereException
     */
75
    public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null)
76
    {
77 78
        assert(is_int($column));

79
        switch ($type) {
80 81
            case ParameterType::INTEGER:
            case ParameterType::BOOLEAN:
82 83
                $type = 'i';
                break;
84 85

            case ParameterType::LARGE_OBJECT:
86 87
                $type = 'b';
                break;
88 89 90

            case ParameterType::NULL:
            case ParameterType::STRING:
91
            case ParameterType::BINARY:
92 93
                $type = 's';
                break;
94

95 96 97 98
            default:
                throw new SQLAnywhereException('Unknown type: ' . $type);
        }

99 100
        $this->boundValues[$column] =& $variable;

101
        if (! sasql_stmt_bind_param_ex($this->stmt, $column - 1, $variable, $type, $variable === null)) {
102 103 104 105 106 107 108 109 110
            throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
111
    public function bindValue($param, $value, $type = ParameterType::STRING)
112 113 114 115 116 117 118 119 120 121 122
    {
        return $this->bindParam($param, $value, $type);
    }

    /**
     * {@inheritdoc}
     *
     * @throws SQLAnywhereException
     */
    public function closeCursor()
    {
123
        if (! sasql_stmt_reset($this->stmt)) {
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
            throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function columnCount()
    {
        return sasql_stmt_field_count($this->stmt);
    }

    /**
     * {@inheritdoc}
     */
    public function errorCode()
    {
        return sasql_stmt_errno($this->stmt);
    }

    /**
     * {@inheritdoc}
     */
    public function errorInfo()
    {
        return sasql_stmt_error($this->stmt);
    }

    /**
     * {@inheritdoc}
     *
     * @throws SQLAnywhereException
     */
    public function execute($params = null)
    {
161
        if ($params !== null) {
162
            $hasZeroIndex = array_key_exists(0, $params);
Steve Müller's avatar
Steve Müller committed
163

164
            foreach ($params as $key => $val) {
Sergei Morozov's avatar
Sergei Morozov committed
165 166 167 168 169
                if ($hasZeroIndex && is_int($key)) {
                    $this->bindValue($key + 1, $val);
                } else {
                    $this->bindValue($key, $val);
                }
170 171 172
            }
        }

173
        if (! sasql_stmt_execute($this->stmt)) {
174 175 176 177 178 179 180 181 182 183 184 185 186
            throw SQLAnywhereException::fromSQLAnywhereError($this->conn, $this->stmt);
        }

        $this->result = sasql_stmt_result_metadata($this->stmt);

        return true;
    }

    /**
     * {@inheritdoc}
     *
     * @throws SQLAnywhereException
     */
187
    public function fetch($fetchMode = null)
188
    {
189
        if (! is_resource($this->result)) {
190 191 192
            return false;
        }

193
        $fetchMode = $fetchMode ?? $this->defaultFetchMode;
194 195

        switch ($fetchMode) {
196
            case FetchMode::COLUMN:
197 198
                return $this->fetchColumn();

199
            case FetchMode::ASSOCIATIVE:
200
                return sasql_fetch_assoc($this->result);
201 202

            case FetchMode::MIXED:
203
                return sasql_fetch_array($this->result, SASQL_BOTH);
204 205

            case FetchMode::NUMERIC:
206
                return sasql_fetch_row($this->result);
207

208 209 210 211 212 213 214 215
            default:
                throw new SQLAnywhereException('Fetch mode is not supported: ' . $fetchMode);
        }
    }

    /**
     * {@inheritdoc}
     */
216
    public function fetchAll($fetchMode = null)
217
    {
218
        $rows = [];
219 220

        switch ($fetchMode) {
221
            case FetchMode::COLUMN:
222
                while (($row = $this->fetchColumn()) !== false) {
223 224 225
                    $rows[] = $row;
                }
                break;
226

227
            default:
228
                while (($row = $this->fetch($fetchMode)) !== false) {
229 230 231 232 233 234 235 236 237 238
                    $rows[] = $row;
                }
        }

        return $rows;
    }

    /**
     * {@inheritdoc}
     */
239
    public function fetchColumn()
240
    {
241
        $row = $this->fetch(FetchMode::NUMERIC);
242

243
        if ($row === false) {
244
            return false;
245 246
        }

247
        return $row[0] ?? null;
248 249 250 251 252 253 254
    }

    /**
     * {@inheritdoc}
     */
    public function getIterator()
    {
255
        return new StatementIterator($this);
256 257 258 259 260
    }

    /**
     * {@inheritdoc}
     */
261
    public function rowCount() : int
262 263 264 265 266 267 268
    {
        return sasql_stmt_affected_rows($this->stmt);
    }

    /**
     * {@inheritdoc}
     */
269
    public function setFetchMode($fetchMode)
270
    {
271 272 273
        $this->defaultFetchMode = $fetchMode;

        return true;
274 275
    }
}