Completed
Push — master ( 6a811e...c52182 )
by Hong
02:35
created

StatementAbstract   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 157
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 12
c 1
b 0
f 0
lcom 1
cbo 4
dl 0
loc 157
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __destruct() 0 4 1
B prepare() 0 23 4
B execute() 0 36 3
A getResult() 0 10 2
A close() 0 7 2
realPrepare() 0 1 ?
realExecute() 0 1 ?
realClose() 0 1 ?
1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Db
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Db\Driver;
16
17
use Phossa2\Db\Message\Message;
18
use Phossa2\Db\Traits\DriverAwareTrait;
19
use Phossa2\Shared\Base\ObjectAbstract;
20
use Phossa2\Db\Interfaces\ResultInterface;
21
use Phossa2\Db\Exception\RuntimeException;
22
use Phossa2\Db\Exception\NotFoundException;
23
use Phossa2\Db\Interfaces\StatementInterface;
24
25
/**
26
 * StatementAbstract
27
 *
28
 * @package Phossa2\Db
29
 * @author  Hong Zhang <[email protected]>
30
 * @see     ObjectAbstract
31
 * @see     StatementInterface
32
 * @version 2.0.0
33
 * @since   2.0.0 added
34
 */
35
abstract class StatementAbstract extends ObjectAbstract implements StatementInterface
36
{
37
    use DriverAwareTrait;
38
39
    /**
40
     * prepared statement
41
     *
42
     * @var    mixed
43
     * @access protected
44
     */
45
    protected $prepared;
46
47
    /**
48
     * Result prototype
49
     *
50
     * @var    ResultInterface
51
     * @access protected
52
     */
53
    protected $result_prototype;
54
55
    /**
56
     * @var    ResultInterface
57
     * @access protected
58
     */
59
    protected $result;
60
61
    /**
62
     * Desctructor
63
     *
64
     * @access public
65
     */
66
    public function __destruct()
67
    {
68
        $this->close();
69
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74
    public function prepare(/*# string */ $sql)/*# : bool */
75
    {
76
        if ($this->prepared) {
77
            return true;
78
        }
79
80
        // prepare statement
81
        try {
82
            $res = $this->realPrepare($this->getDriver()->getLink(),$sql);
83
84
            if (false !== $res) {
85
                $this->prepared = $res;
86
                $this->getDriver()->getProfiler()->setSql($sql);
87
                return true;
88
            }
89
        } catch (\Exception $e) {
90
            throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
91
        }
92
        throw new RuntimeException(
93
            Message::get(Message::DB_STMT_PREPARE_FAIL, $sql),
94
            Message::DB_STMT_PREPARE_FAIL
95
        );
96
    }
97
98
    /**
99
     * {@inheritDoc}
100
     */
101
    public function execute(array $parameters = [])/*# : bool */
102
    {
103
        if (null === $this->prepared) {
104
            throw new RuntimeException(
105
                Message::get(Message::DB_STMT_NOTPREPARED),
106
                Message::DB_STMT_NOTPREPARED
107
            );
108
        }
109
110
        // close previous result for this statement
111
        $this->close();
112
113
        // start time
114
        $time = microtime(true);
115
        $this->getDriver()->getProfiler()->setParameters($parameters);
116
117
        if ($this->realExecute($parameters)) {
118
            $result = clone $this->result_prototype;
119
            $result($this->prepared);
120
            $this->result = $result;
121
122
            // profiling
123
            $this->getDriver()->getProfiler()
124
                ->setExecutionTime(microtime(true) - $time);
125
126
            return true;
127
        }
128
129
        throw new RuntimeException(
130
            Message::get(
131
                Message::DB_STMT_EXECUTE_FAIL,
132
                $this->getDriver()->getProfiler()->getSql()
133
            ),
134
            Message::DB_STMT_EXECUTE_FAIL
135
        );
136
    }
137
138
    /**
139
     * {@inheritDoc}
140
     */
141
    public function getResult()/*# : ResultInterface */
142
    {
143
        if (null === $this->result) {
144
            throw new NotFoundException(
145
                Message::get(Message::DB_STMT_NO_RESULT),
146
                Message::DB_STMT_NO_RESULT
147
            );
148
        }
149
        return $this->result;
150
    }
151
152
    /**
153
     * {@inheritDoc}
154
     */
155
    public function close()
156
    {
157
        if ($this->prepared) {
158
            $this->realClose($this->prepared);
159
            $this->result = null;
160
        }
161
    }
162
163
    /**
164
     * Driver specific prepare statement
165
     *
166
     * @param  mixed $link db link resource
167
     * @param  string $sql
168
     * @return mixed
169
     * @throws RuntimeException
170
     * @access protected
171
     */
172
    abstract protected function realPrepare($link, /*# string */ $sql);
173
174
    /**
175
     * Driver specific statement execution
176
     *
177
     * @param  array $parameters
178
     * @return bool
179
     * @throws RuntimeException
180
     * @access protected
181
     */
182
    abstract protected function realExecute(array $parameters)/*# : bool */;
183
184
    /**
185
     * Close statement's result set
186
     *
187
     * @param  mixed prepared low-level statement
188
     * @access protected
189
     */
190
    abstract protected function realClose($stmt);
191
}
192