Completed
Push — master ( a1178b...339ab1 )
by Rasmus
03:22
created

PreparedPDOStatement::fetch()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 14
ccs 7
cts 7
cp 1
rs 9.4285
cc 3
eloc 7
nc 4
nop 0
crap 3
1
<?php
2
3
namespace mindplay\sql\framework\pdo;
4
5
use InvalidArgumentException;
6
use mindplay\sql\framework\Logger;
7
use mindplay\sql\framework\PreparedStatement;
8
use mindplay\sql\model\Driver;
9
use mindplay\sql\model\TypeProvider;
10
use PDO;
11
use PDOStatement;
12
13
/**
14
 * This class implements a Prepared Statement adapter for PDO Statements.
15
 */
16
class PreparedPDOStatement implements PreparedStatement
17
{
18
    /**
19
     * @var PDOStatement
20
     */
21
    private $handle;
22
23
    /**
24
     * @var PDOExceptionMapper
25
     */
26
    private $exception_mapper;
27
28
    /**
29
     * @var TypeProvider
30
     */
31
    private $types;
32
33
    /**
34
     * @var array
35
     */
36
    private $params = [];
37
38
    /**
39
     * @var bool
40
     */
41
    private $executed = false;
42
43
    /**
44
     * @var Logger
45
     */
46
    private $logger;
47
48
    /**
49
     * @param PDOStatement       $handle
50
     * @param PDOExceptionMapper $exception_mapper
51
     * @param TypeProvider       $types
52
     * @param Logger             $logger
53
     */
54 1
    public function __construct(
55
        PDOStatement $handle,
56
        PDOExceptionMapper $exception_mapper,
57
        TypeProvider $types,
58
        Logger $logger
59
    ) {
60 1
        $this->handle = $handle;
61 1
        $this->exception_mapper = $exception_mapper;
62 1
        $this->types = $types;
63 1
        $this->logger = $logger;
64 1
    }
65
66
    /**
67
     * @inheritdoc
68
     */
69 1
    public function bind($name, $value)
70
    {
71 1
        static $PDO_TYPE = [
72
            'integer' => PDO::PARAM_INT,
73
            'double'  => PDO::PARAM_STR, // bind as string, since there's no float type in PDO
74
            'string'  => PDO::PARAM_STR,
75
            'boolean' => PDO::PARAM_BOOL,
76
            'NULL'    => PDO::PARAM_NULL,
77
        ];
78
79 1
        $value_type = gettype($value);
80
81 1
        $scalar_type = "scalar.{$value_type}";
82
83 1
        if ($this->types->hasType($scalar_type)) {
84 1
            $type = $this->types->getType($scalar_type);
85
86 1
            $value = $type->convertToSQL($value);
87
88 1
            $value_type = gettype($value);
89
        }
90
91 1
        if (isset($PDO_TYPE[$value_type])) {
92 1
            $this->handle->bindValue($name, $value, $PDO_TYPE[$value_type]);
93
94 1
            $this->params[$name] = $value;
95
        } else {
96 1
            throw new InvalidArgumentException("unexpected value type: {$value_type}");
97
        }
98 1
    }
99
100
    /**
101
     * @inheritdoc
102
     */
103 1
    public function execute()
104
    {
105 1
        $microtime_begin = microtime(true);
106
107 1
        if (@$this->handle->execute()) {
108 1
            $this->executed = true;
109 1
            $microtime_end = microtime(true);
110 1
            $time_msec = ($microtime_end - $microtime_begin) * 1000;
111 1
            $this->logger->logQuery($this->handle->queryString, $this->params, $time_msec);
112
        } else {
113
            list($sql_state, $error_code, $error_message) = $this->handle->errorInfo();
114
115
            $exception_type = $this->exception_mapper->getExceptionType($sql_state, $error_code, $error_message);
116
117
            throw new $exception_type(
118
                $this->handle->queryString,
119
                $this->params,
120
                "{$sql_state}: {$error_message}",
121
                $error_code
122
            );
123
        }
124 1
    }
125
126
    /**
127
     * @inheritdoc
128
     */
129 1
    public function fetch()
130
    {
131 1
        if (! $this->executed) {
132 1
            $this->execute();
133
        }
134
135 1
        $result = $this->handle->fetch(PDO::FETCH_ASSOC);
136
137 1
        if ($result === false) {
138 1
            return null;
139
        }
140
141 1
        return $result;
142
    }
143
144
    /**
145
     * @inheritdoc
146
     */
147
    public function getRowsAffected()
148
    {
149
        return $this->handle->rowCount();
150
    }
151
}
152