Completed
Push — master ( 471540...e3dcd8 )
by Rasmus
03:02
created

PreparedPDOStatement   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 85.29%

Importance

Changes 3
Bugs 0 Features 1
Metric Value
wmc 10
c 3
b 0
f 1
lcom 1
cbo 3
dl 0
loc 116
ccs 29
cts 34
cp 0.8529
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
B bind() 0 30 3
A execute() 0 13 2
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\PreparedStatement;
7
use mindplay\sql\model\Driver;
8
use mindplay\sql\model\TypeProvider;
9
use PDO;
10
use PDOStatement;
11
12
/**
13
 * This class implements a Prepared Statement adapter for PDO Statements.
14
 */
15
class PreparedPDOStatement implements PreparedStatement
16
{
17
    /**
18
     * @var PDOStatement
19
     */
20
    private $handle;
21
22
    /**
23
     * @var PDOExceptionMapper
24
     */
25
    private $exception_mapper;
26
27
    /**
28
     * @var TypeProvider
29
     */
30
    private $types;
31
32
    /**
33
     * @var array
34
     */
35
    private $params = [];
36
37
    /**
38
     * @var bool
39
     */
40
    private $executed = false;
41
42
    /**
43
     * @param PDOStatement       $handle
44
     * @param PDOExceptionMapper $exception_mapper
45
     * @param TypeProvider       $types
46
     */
47 1
    public function __construct(PDOStatement $handle, PDOExceptionMapper $exception_mapper, TypeProvider $types)
48
    {
49 1
        $this->handle = $handle;
50 1
        $this->exception_mapper = $exception_mapper;
51 1
        $this->types = $types;
52 1
    }
53
54
    /**
55
     * @inheritdoc
56
     */
57 1
    public function bind($name, $value)
58
    {
59 1
        static $PDO_TYPE = [
60
            'integer' => PDO::PARAM_INT,
61
            'double'  => PDO::PARAM_STR, // bind as string, since there's no float type in PDO
62
            'string'  => PDO::PARAM_STR,
63
            'boolean' => PDO::PARAM_BOOL,
64
            'NULL'    => PDO::PARAM_NULL,
65
        ];
66
67 1
        $value_type = gettype($value);
68
69 1
        $scalar_type = "scalar.{$value_type}";
70
71 1
        if ($this->types->hasType($scalar_type)) {
72 1
            $type = $this->types->getType($scalar_type);
73
74 1
            $value = $type->convertToSQL($value);
75
76 1
            $value_type = gettype($value);
77
        }
78
79 1
        if (isset($PDO_TYPE[$value_type])) {
80 1
            $this->handle->bindValue($name, $value, $PDO_TYPE[$value_type]);
81
82 1
            $this->params[$name] = $value;
83
        } else {
84 1
            throw new InvalidArgumentException("unexpected value type: {$value_type}");
85
        }
86 1
    }
87
88
    /**
89
     * @inheritdoc
90
     */
91 1
    public function execute()
92
    {
93 1
        if (@$this->handle->execute()) {
94 1
            $this->executed = true;
95
        } else {
96
            list($sql_state, $error_code, $error_message) = $this->handle->errorInfo();
97
98
            $exception_type = $this->exception_mapper->getExceptionType($sql_state, $error_code, $error_message);
99
100
            throw new $exception_type($this->handle->queryString, $this->params, "{$sql_state}: {$error_message}",
101
                $error_code);
102
        }
103 1
    }
104
105
    /**
106
     * @inheritdoc
107
     */
108 1
    public function fetch()
109
    {
110 1
        if (! $this->executed) {
111 1
            $this->execute();
112
        }
113
114 1
        $result = $this->handle->fetch(PDO::FETCH_ASSOC);
115
116 1
        if ($result === false) {
117 1
            return null;
118
        }
119
120 1
        return $result;
121
    }
122
123
    /**
124
     * @inheritdoc
125
     */
126
    public function getRowsAffected()
127
    {
128
        return $this->handle->rowCount();
129
    }
130
}
131