InsertQuery   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Test Coverage

Coverage 87.8%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 39
c 1
b 0
f 0
dl 0
loc 99
ccs 36
cts 41
cp 0.878
rs 10
wmc 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getSQL() 0 19 2
A __construct() 0 16 2
A add() 0 27 4
1
<?php
2
3
namespace mindplay\sql\model\query;
4
5
use mindplay\sql\model\Driver;
6
use mindplay\sql\model\schema\Column;
7
use mindplay\sql\model\schema\Table;
8
use mindplay\sql\model\TypeProvider;
9
use RuntimeException;
10
11
/**
12
 * This class represents an INSERT query.
13
 */
14
class InsertQuery extends Query
15
{
16
    private Driver $driver;
17
    private Table $table;
18
19
    /**
20
     * @var Column[]
21
     */
22
    private array $columns;
23
24
    /**
25
     * @var string[] list of tuple expressions
26
     */
27
    private $tuples = [];
28
29
    /**
30
     * @param Driver       $driver
31
     * @param TypeProvider $types
32
     * @param Table        $table Table to INSERT into
33
     */
34 1
    public function __construct(Driver $driver, TypeProvider $types, Table $table)
35
    {
36 1
        parent::__construct($types);
37
38 1
        if ($table->getAlias()) {
39
            throw new RuntimeException("can't insert into a Table instance with an alias");
40
        }
41
42 1
        $this->driver = $driver;
43
44 1
        $this->table = $table;
45
46 1
        $this->columns = array_filter(
47 1
            $table->listColumns(),
48 1
            function (Column $column) {
49 1
                return $column->isAuto() === false;
50 1
            }
51 1
        );
52
    }
53
54
55
    /**
56
     * Add a record to this INSERT query.
57
     *
58
     * @param array<string,mixed> $record record map (where Column name => value)
59
     *
60
     * @return $this
61
     */
62 1
    public function add(array $record): static
63
    {
64 1
        $placeholders = [];
65
66 1
        $tuple_num = count($this->tuples);
67
68 1
        foreach ($this->columns as $col_index => $column) {
69 1
            $name = $column->getName();
70
71 1
            if (array_key_exists($name, $record)) {
72 1
                $value = $record[$name];
73
            } elseif ($column->isRequired() === false) {
74
                $value = $column->getDefault();
75
            } else {
76
                throw new RuntimeException("required value '{$name}' missing from tuple # {$tuple_num}");
77
            }
78
79 1
            $placeholder = "c{$tuple_num}_{$col_index}";
80
81 1
            $placeholders[] = ":{$placeholder}";
82
83 1
            $this->bind($placeholder, $value, $column->getType());
84
        }
85
86 1
        $this->tuples[] = "(" . implode(", ", $placeholders) . ")";
87
88 1
        return $this;
89
    }
90
91
    /**
92
     * @inheritdoc
93
     */
94 1
    public function getSQL(): string
95
    {
96 1
        if (count($this->tuples) === 0) {
97
            throw new RuntimeException("no records added to this query");
98
        }
99
100 1
        $table = "{$this->table}";
101
102 1
        $quoted_column_names = implode(
103 1
            ", ",
104 1
            array_map(
105 1
                function (Column $column) {
106 1
                    return $this->driver->quoteName($column->getName());
107 1
                },
108 1
                $this->columns
109 1
            )
110 1
        );
111
112 1
        return "INSERT INTO {$table} ({$quoted_column_names}) VALUES\n" . implode(",\n", $this->tuples);
113
    }
114
}
115