Passed
Push — dev ( 4d1626...1e4d6c )
by 世昌
02:25
created

WriteStatement   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 259
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 80
dl 0
loc 259
rs 10
c 1
b 0
f 0
wmc 28

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A write() 0 13 5
A wantId() 0 4 1
A wantOk() 0 4 1
A delete() 0 4 1
A where() 0 15 4
A aliasKeyField() 0 8 2
A whereCondition() 0 4 1
A wantRows() 0 4 1
A arrayWhereCondition() 0 6 2
A prepareWriteField() 0 6 2
A prepareInsert() 0 14 2
A prepareQuery() 0 17 5
1
<?php
2
3
namespace suda\database\statement;
4
5
use function implode;
6
use function is_array;
7
use function is_string;
8
use function sprintf;
9
use suda\database\Binder;
10
use suda\database\struct\TableStruct;
11
use suda\database\middleware\Middleware;
12
use suda\database\exception\SQLException;
13
14
class WriteStatement extends Statement
15
{
16
    use PrepareTrait;
17
18
    /**
19
     * 数据
20
     *
21
     * @var array|string
22
     */
23
    protected $data;
24
25
    /**
26
     * 数据表结构
27
     *
28
     * @var TableStruct
29
     */
30
    protected $struct;
31
32
    /**
33
     * 数据原始表名
34
     *
35
     * @var string
36
     */
37
    protected $table;
38
39
    /**
40
     * 模板条件条件
41
     *
42
     * @var string|null
43
     */
44
    protected $whereCondition = null;
45
46
    /**
47
     * 是否为删除
48
     *
49
     * @var bool
50
     */
51
    protected $delete = false;
52
53
54
    /**
55
     * 创建写
56
     *
57
     * @param string $rawTableName
58
     * @param TableStruct $struct
59
     * @param Middleware $middleware
60
     * @throws SQLException
61
     */
62
    public function __construct(string $rawTableName, TableStruct $struct, Middleware $middleware)
63
    {
64
        parent::__construct('');
65
        $this->type = self::WRITE;
66
        $this->struct = $struct;
67
        $this->table = $rawTableName;
68
        $this->middleware = $middleware;
69
    }
70
71
    /**
72
     * 写数据
73
     *
74
     * @param string|array $name
75
     * @param mixed $value
76
     * @return $this
77
     * @throws SQLException
78
     */
79
    public function write($name, $value = null)
80
    {
81
        $argcount = func_num_args();
82
        if (is_array($name)) {
83
            foreach ($name as $key => $value) {
84
                $this->write($key, $value);
85
            }
86
        } elseif (is_string($name) && $argcount >= 2) {
87
            $this->prepareWriteField($name, $value);
88
        } else {
89
            $this->data = $name;
90
        }
91
        return $this;
92
    }
93
94
    /**
95
     * 准备字段
96
     *
97
     * @param string $name
98
     * @param mixed $value
99
     * @return void
100
     * @throws SQLException
101
     */
102
    private function prepareWriteField(string $name, $value) {
103
        $name = $this->middleware->inputName($name);
104
        if ($this->struct->hasField($name)) {
105
            $this->data[$name] = $value;
106
        } else {
107
            throw new SQLException(sprintf('table %s has no field %s', $this->struct->getName(), $name));
108
        }
109
    }
110
111
    /**
112
     * 设置影响行数
113
     *
114
     * @return $this
115
     */
116
    public function wantRows()
117
    {
118
        $this->returnType = WriteStatement::RET_ROWS;
119
        return $this;
120
    }
121
122
    /**
123
     * 设置返回是否成功
124
     *
125
     * @return $this
126
     */
127
    public function wantOk()
128
    {
129
        $this->returnType = WriteStatement::RET_BOOL;
130
        return $this;
131
    }
132
133
    /**
134
     * 设置返回ID
135
     *
136
     * @return $this
137
     */
138
    public function wantId()
139
    {
140
        $this->returnType = WriteStatement::RET_LAST_INSERT_ID;
141
        return $this;
142
    }
143
144
    /**
145
     * 删除
146
     *
147
     * @return $this
148
     */
149
    public function delete()
150
    {
151
        $this->delete = true;
152
        return $this;
153
    }
154
155
    /**
156
     * 条件查询
157
     *
158
     * @param string|array $where
159
     * @param array $args
160
     * @return $this
161
     * @throws SQLException
162
     */
163
    public function where($where, ...$args)
164
    {
165
        if (is_string($where)) {
166
            if (count($args) > 0 && is_array($args[0])) {
167
                $whereParameter = $args[0];
168
                $this->whereCondition($where, $whereParameter);
169
            } else {
170
                list($string, $array) = $this->prepareQueryMark($where, $args);
171
                $this->whereCondition($string, $array);
172
            }
173
        } else {
174
            $this->aliasKeyField($where);
175
            $this->arrayWhereCondition($where, $args[0] ?? []);
176
        }
177
        return $this;
178
    }
179
180
    /**
181
     * 处理输入的键
182
     *
183
     * @param array $fields
184
     * @return array
185
     */
186
    protected function aliasKeyField(array $fields)
187
    {
188
        $values = [];
189
        foreach ($fields as $name => $value) {
190
            $index = $this->middleware->inputName($name);
191
            $values[$index] = $value;
192
        }
193
        return $values;
194
    }
195
196
    /**
197
     * 获取字符串
198
     *
199
     * @return Query
200
     */
201
    protected function prepareQuery(): Query
202
    {
203
        if (is_array($this->data) && $this->whereCondition === null) {
204
            return $this->prepareInsert($this->data);
205
        } else {
206
            if ($this->delete === false) {
207
                if (is_string($this->data)) {
208
                    $updateSet = trim($this->data);
209
                } else {
210
                    list($updateSet, $upBinder) = $this->prepareUpdateSet($this->data);
211
                    $this->binder = array_merge($this->binder, $upBinder);
212
                }
213
                $string = "UPDATE " . $this->table . " SET " . $updateSet . " WHERE " . $this->whereCondition;
214
                return new Query($string, $this->binder);
215
            } else {
216
                $string = "DELETE FROM " . $this->table . " WHERE " . $this->whereCondition;
217
                return new Query($string, $this->binder);
218
            }
219
        }
220
    }
221
222
    /**
223
     * 字符串式绑定
224
     *
225
     * @param string $where
226
     * @param array $whereParameter
227
     * @return void
228
     * @throws SQLException
229
     */
230
    protected function whereCondition(string $where, array $whereParameter)
231
    {
232
        list($this->whereCondition, $whereBinder) = $this->prepareWhereString($where, $whereParameter);
233
        $this->binder = array_merge($this->binder, $whereBinder);
234
    }
235
236
    /**
237
     * 数组条件式绑定
238
     *
239
     * @param array $where
240
     * @param array $whereParameter
241
     * @return void
242
     * @throws SQLException
243
     */
244
    protected function arrayWhereCondition(array $where, array $whereParameter)
245
    {
246
        list($this->whereCondition, $whereBinder) = $this->prepareWhere($where);
247
        $this->binder = array_merge($this->binder, $whereBinder);
248
        foreach ($whereParameter as $key => $value) {
249
            $this->binder[] = new Binder($key, $value);
250
        }
251
    }
252
253
    /**
254
     * 准备插入语句
255
     *
256
     * @param array $data
257
     * @return Query
258
     */
259
    public function prepareInsert(array $data): Query
260
    {
261
        $names = [];
262
        $binds = [];
263
        $this->binder;
264
        foreach ($data as $name => $value) {
265
            $_name = Binder::index($name);
266
            $this->binder[] = new Binder($_name, $value, $name);
267
            $names[] = "`{$name}`";
268
            $binds[] = ":{$_name}";
269
        }
270
        $i_name = implode(',', $names);
271
        $i_bind = implode(',', $binds);
272
        return new Query(sprintf('INSERT INTO %s (%s) VALUES (%s)', $this->table, $i_name, $i_bind), $this->binder);
273
    }
274
}
275