SQLSrvConnection.php 4.48 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\DBAL\Driver\SQLSrv;

Steve Müller's avatar
Steve Müller committed
5
use Doctrine\DBAL\Driver\Connection;
6
use Doctrine\DBAL\Driver\Result;
7
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
8
use Doctrine\DBAL\ParameterType;
9

10 11 12 13 14 15 16 17 18 19 20 21 22 23
use function func_get_args;
use function is_float;
use function is_int;
use function sprintf;
use function sqlsrv_begin_transaction;
use function sqlsrv_commit;
use function sqlsrv_configure;
use function sqlsrv_connect;
use function sqlsrv_errors;
use function sqlsrv_query;
use function sqlsrv_rollback;
use function sqlsrv_rows_affected;
use function sqlsrv_server_info;
use function str_replace;
24

Grégoire Paris's avatar
Grégoire Paris committed
25
use const SQLSRV_ERR_ERRORS;
Steve Müller's avatar
Steve Müller committed
26

27 28 29
/**
 * SQL Server implementation for the Connection interface.
 */
30
class SQLSrvConnection implements Connection, ServerInfoAwareConnection
31
{
32
    /** @var resource */
33 34
    protected $conn;

35
    /** @var LastInsertId */
36 37
    protected $lastInsertId;

Benjamin Morel's avatar
Benjamin Morel committed
38
    /**
39 40
     * @param string  $serverName
     * @param mixed[] $connectionOptions
Benjamin Morel's avatar
Benjamin Morel committed
41
     *
42
     * @throws SQLSrvException
Benjamin Morel's avatar
Benjamin Morel committed
43
     */
44 45
    public function __construct($serverName, $connectionOptions)
    {
46
        if (! sqlsrv_configure('WarningsReturnAsErrors', 0)) {
47 48 49
            throw SQLSrvException::fromSqlSrvErrors();
        }

Sergei Morozov's avatar
Sergei Morozov committed
50 51 52
        $conn = sqlsrv_connect($serverName, $connectionOptions);

        if ($conn === false) {
53 54
            throw SQLSrvException::fromSqlSrvErrors();
        }
Sergei Morozov's avatar
Sergei Morozov committed
55 56

        $this->conn         = $conn;
57
        $this->lastInsertId = new LastInsertId();
58 59
    }

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
    /**
     * {@inheritdoc}
     */
    public function getServerVersion()
    {
        $serverInfo = sqlsrv_server_info($this->conn);

        return $serverInfo['SQLServerVersion'];
    }

    /**
     * {@inheritdoc}
     */
    public function requiresQueryForServerVersion()
    {
        return false;
    }

78 79 80 81 82
    /**
     * {@inheritDoc}
     */
    public function prepare($sql)
    {
Benjamin Eberlei's avatar
Benjamin Eberlei committed
83
        return new SQLSrvStatement($this->conn, $sql, $this->lastInsertId);
84 85 86 87 88 89 90 91
    }

    /**
     * {@inheritDoc}
     */
    public function query()
    {
        $args = func_get_args();
92
        $sql  = $args[0];
93 94
        $stmt = $this->prepare($sql);
        $stmt->execute();
Benjamin Morel's avatar
Benjamin Morel committed
95

96 97 98 99 100 101
        return $stmt;
    }

    /**
     * {@inheritDoc}
     */
102
    public function quote($value, $type = ParameterType::STRING)
103 104 105
    {
        if (is_int($value)) {
            return $value;
106 107 108
        }

        if (is_float($value)) {
109 110 111 112 113 114 115 116 117 118 119
            return sprintf('%F', $value);
        }

        return "'" . str_replace("'", "''", $value) . "'";
    }

    /**
     * {@inheritDoc}
     */
    public function exec($statement)
    {
120 121
        $stmt = sqlsrv_query($this->conn, $statement);

122
        if ($stmt === false) {
123 124
            throw SQLSrvException::fromSqlSrvErrors();
        }
Benjamin Morel's avatar
Benjamin Morel committed
125

Sergei Morozov's avatar
Sergei Morozov committed
126 127 128 129 130 131 132
        $rowsAffected = sqlsrv_rows_affected($stmt);

        if ($rowsAffected === false) {
            throw SQLSrvException::fromSqlSrvErrors();
        }

        return $rowsAffected;
133 134 135 136 137 138 139
    }

    /**
     * {@inheritDoc}
     */
    public function lastInsertId($name = null)
    {
140
        if ($name !== null) {
141
            $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?');
142
            $stmt->execute([$name]);
143 144
        } else {
            $stmt = $this->query('SELECT @@IDENTITY');
145 146
        }

147
        if ($stmt instanceof Result) {
148 149 150
            return $stmt->fetchOne();
        }

151
        return $stmt->fetchColumn();
152 153 154 155 156 157 158
    }

    /**
     * {@inheritDoc}
     */
    public function beginTransaction()
    {
159
        if (! sqlsrv_begin_transaction($this->conn)) {
160 161
            throw SQLSrvException::fromSqlSrvErrors();
        }
162 163

        return true;
164 165 166 167 168 169 170
    }

    /**
     * {@inheritDoc}
     */
    public function commit()
    {
171
        if (! sqlsrv_commit($this->conn)) {
172 173
            throw SQLSrvException::fromSqlSrvErrors();
        }
174 175

        return true;
176 177 178 179 180 181 182
    }

    /**
     * {@inheritDoc}
     */
    public function rollBack()
    {
183
        if (! sqlsrv_rollback($this->conn)) {
184 185
            throw SQLSrvException::fromSqlSrvErrors();
        }
186 187

        return true;
188 189 190 191
    }

    /**
     * {@inheritDoc}
192 193
     *
     * @deprecated The error information is available via exceptions.
194 195 196 197 198 199 200
     */
    public function errorCode()
    {
        $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
        if ($errors) {
            return $errors[0]['code'];
        }
Benjamin Morel's avatar
Benjamin Morel committed
201

202 203 204 205 206
        return false;
    }

    /**
     * {@inheritDoc}
207 208
     *
     * @deprecated The error information is available via exceptions.
209 210 211
     */
    public function errorInfo()
    {
Sergei Morozov's avatar
Sergei Morozov committed
212
        return (array) sqlsrv_errors(SQLSRV_ERR_ERRORS);
213 214
    }
}