Completed
Pull Request — master (#23)
by
unknown
02:32
created

PreparedPDOStatement   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 87.5%

Importance

Changes 4
Bugs 0 Features 2
Metric Value
c 4
b 0
f 2
dl 0
loc 130
wmc 11
lcom 1
cbo 4
ccs 35
cts 40
cp 0.875
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B bind() 0 30 3
A execute() 0 20 3
A fetch() 0 14 3
A getRowsAffected() 0 4 1
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
0 ignored issues
show
Documentation introduced by
Should the type for parameter $logger not be null|Logger?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
53
     */
54 1
    public function __construct(PDOStatement $handle, PDOExceptionMapper $exception_mapper, TypeProvider $types, Logger $logger = null)
55
    {
56 1
        $this->handle = $handle;
57 1
        $this->exception_mapper = $exception_mapper;
58 1
        $this->types = $types;
59 1
        $this->logger = $logger;
60 1
    }
61
62
    /**
63
     * @inheritdoc
64
     */
65 1
    public function bind($name, $value)
66
    {
67 1
        static $PDO_TYPE = [
68
            'integer' => PDO::PARAM_INT,
69
            'double'  => PDO::PARAM_STR, // bind as string, since there's no float type in PDO
70
            'string'  => PDO::PARAM_STR,
71
            'boolean' => PDO::PARAM_BOOL,
72
            'NULL'    => PDO::PARAM_NULL,
73
        ];
74
75 1
        $value_type = gettype($value);
76
77 1
        $scalar_type = "scalar.{$value_type}";
78
79 1
        if ($this->types->hasType($scalar_type)) {
80 1
            $type = $this->types->getType($scalar_type);
81
82 1
            $value = $type->convertToSQL($value);
83
84 1
            $value_type = gettype($value);
85
        }
86
87 1
        if (isset($PDO_TYPE[$value_type])) {
88 1
            $this->handle->bindValue($name, $value, $PDO_TYPE[$value_type]);
89
90 1
            $this->params[$name] = $value;
91
        } else {
92 1
            throw new InvalidArgumentException("unexpected value type: {$value_type}");
93
        }
94 1
    }
95
96
    /**
97
     * @inheritdoc
98
     */
99 1
    public function execute()
100
    {
101 1
        $microtime_begin = microtime(true);
102
103 1
        if (@$this->handle->execute()) {
104 1
            $this->executed = true;
105 1
            if (isset($this->logger)) {
106 1
                $microtime_end = microtime(true);
107 1
                $time_msec = ($microtime_end - $microtime_begin) * 1000;
108 1
                $this->logger->logQuery($this->handle->queryString, $this->params, $time_msec);
109
            }
110
        } else {
111
            list($sql_state, $error_code, $error_message) = $this->handle->errorInfo();
112
113
            $exception_type = $this->exception_mapper->getExceptionType($sql_state, $error_code, $error_message);
114
115
            throw new $exception_type($this->handle->queryString, $this->params, "{$sql_state}: {$error_message}",
116
                $error_code);
117
        }
118 1
    }
119
120
    /**
121
     * @inheritdoc
122
     */
123 1
    public function fetch()
124
    {
125 1
        if (! $this->executed) {
126 1
            $this->execute();
127
        }
128
129 1
        $result = $this->handle->fetch(PDO::FETCH_ASSOC);
130
131 1
        if ($result === false) {
132 1
            return null;
133
        }
134
135 1
        return $result;
136
    }
137
138
    /**
139
     * @inheritdoc
140
     */
141
    public function getRowsAffected()
142
    {
143
        return $this->handle->rowCount();
144
    }
145
}
146