Passed
Branch master (9fb78e)
by Rasmus
12:50
created

UpdateQuery::getSQL()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0116

Importance

Changes 0
Metric Value
cc 2
eloc 6
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 11
ccs 6
cts 7
cp 0.8571
crap 2.0116
rs 10
1
<?php
2
3
namespace mindplay\sql\model\query;
4
5
use mindplay\sql\model\components\Conditions;
6
use mindplay\sql\model\Driver;
7
use mindplay\sql\model\schema\Column;
8
use mindplay\sql\model\schema\Table;
9
use mindplay\sql\model\TypeProvider;
10
11
/**
12
 * This class represents an UPDATE query.
13
 */
14
class UpdateQuery extends Query
15
{
16
    use Conditions;
17
18
    protected Table $table;
19
    protected Driver $driver;
20
21
    /**
22
     * @var array<string,string> map where Column name => literal SQL expression to assign
23
     */
24
    private $assignments = [];
25
26
    /**
27
     * @param Table        $table
28
     * @param TypeProvider $types
29
     */
30 1
    public function __construct(Table $table, Driver $driver, TypeProvider $types)
31
    {
32 1
        parent::__construct($types);
33
34 1
        $this->table = $table;
35 1
        $this->driver = $driver;
36
    }
37
38
    /**
39
     * @param Column|string $column Column to update (or Column name)
40
     * @param mixed         $value  value to apply
41
     *
42
     * @return $this
43
     */
44 1
    public function setValue(Column|string $column, mixed $value): static
45
    {
46
        // TODO qualify table-references to support UPDATE queries with JOINs
47
48 1
        if ($column instanceof Column) {
49 1
            $name = $this->getPlaceholder($column);
50 1
            $type = $column->getType();
51
52 1
            $quoted_name = $this->driver->quoteName($column->getName());
53
        } else {
54
            $name = $column;
55
            $type = null;
56
57
            $quoted_name = $this->driver->quoteName($name);
58
        }
59
60 1
        $this->assignments[$name] = "{$quoted_name} = :{$name}";
61
62 1
        $this->bind($name, $value, $type);
63
64 1
        return $this;
65
    }
66
67
    /**
68
     * @param Column|string $column Column to update (or Column name)
69
     * @param string        $expr   literal SQL expression
70
     *
71
     * @return $this
72
     */
73 1
    public function setExpr(Column|string $column, string $expr): static
74
    {
75
        // TODO qualify table-references to support UPDATE queries with JOINs
76
77 1
        if ($column instanceof Column) {
78 1
            $name = $this->getPlaceholder($column);
79
80 1
            $quoted_name = $this->driver->quoteName($column->getName());
81
        } else {
82
            $name = $column;
83
84
            $quoted_name = $this->driver->quoteName($name);
85
        }
86
87 1
        $this->assignments[$name] = "{$quoted_name} = {$expr}";
88
89 1
        return $this;
90
    }
91
92
    /**
93
     * @param array<string,int|string|bool|null> $values map where Column name => scalar values to assign
94
     *
95
     * @return $this
96
     */
97 1
    public function assign(array $values)
98
    {
99 1
        $columns = $this->table->listColumns();
100
101 1
        foreach ($columns as $column) {
102 1
            $name = $column->getName();
103
104 1
            if (array_key_exists($name, $values)) {
105 1
                $this->setValue($column, $values[$name]);
106
            }
107
        }
108
109 1
        return $this;
110
    }
111
112
    /**
113
     * @inheritdoc
114
     */
115 1
    public function getSQL(): string
116
    {
117 1
        $update = "UPDATE " . $this->table->getNode();
118
119 1
        $set = "\nSET " . implode(",\n    ", $this->assignments);
120
121 1
        $where = count($this->conditions)
122 1
            ? "\nWHERE " . $this->buildConditions()
123
            : ''; // no conditions present
124
125 1
        return "{$update}{$set}{$where}";
126
    }
127
128
    /**
129
     * @param Column $column
130
     *
131
     * @return string
132
     */
133 1
    private function getPlaceholder(Column $column): string
134
    {
135 1
        $table = $column->getTable();
136
137 1
        $table_name = $table->getAlias() ?: $table->getName();
138
139 1
        $column_name = $column->getName();
140
141 1
        $name = "{$table_name}_{$column_name}";
142
143 1
        return $name;
144
    }
145
}
146