Completed
Push — master ( f5e5fb...7d0a28 )
by Rasmus
02:24
created

PreparedPDOStatement::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 3
crap 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 Driver
24
     */
25
    private $driver;
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 Driver       $driver
45
     * @param TypeProvider $types
46
     */
47 1
    public function __construct(PDOStatement $handle, Driver $driver, TypeProvider $types)
48
    {
49 1
        $this->handle = $handle;
50 1
        $this->driver = $driver;
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
            $type = $this->types->getType($scalar_type);
73
74
            $value = $type->convertToSQL($value);
75
76
            $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->driver->getExceptionType($sql_state, $error_code, $error_message);
99
100
            throw new $exception_type($this->handle->queryString, $this->params, "{$sql_state}: {$error_message}", $error_code);
101
        }
102 1
    }
103
104
    /**
105
     * @inheritdoc
106
     */
107 1
    public function fetch()
108
    {
109 1
        if (! $this->executed) {
110 1
            $this->execute();
111
        }
112
113 1
        $result = $this->handle->fetch(PDO::FETCH_ASSOC);
114
        
115 1
        if ($result === false) {
116 1
            return null;
117
        }
118
        
119 1
        return $result;
120
    }
121
122
    /**
123
     * @inheritdoc
124
     */
125
    public function getRowsAffected()
126
    {
127
        return $this->handle->rowCount();
128
    }
129
}
130