Completed
Push — master ( f707f5...a08928 )
by Rasmus
02:27
created

InsertQuery::add()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4.128

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 28
ccs 12
cts 15
cp 0.8
rs 8.5806
cc 4
eloc 16
nc 4
nop 1
crap 4.128
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
    /**
17
     * @var Driver
18
     */
19
    private $driver;
20
21
    /**
22
     * @var Table
23
     */
24
    private $table;
25
26
    /**
27
     * @var Column[]
28
     */
29
    private $columns;
30
31
    /**
32
     * @var string[] list of tuple expressions
33
     */
34
    private $tuples = [];
35
36
    /**
37
     * @param Driver       $driver
38
     * @param TypeProvider $types
39
     * @param Table        $table Table to INSERT into
40
     */
41 1
    public function __construct(Driver $driver, TypeProvider $types, Table $table)
42
    {
43 1
        parent::__construct($types);
44
45 1
        if ($table->getAlias()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $table->getAlias() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
46
            throw new RuntimeException("can't insert into a Table instance with an alias");
47
        }
48
49 1
        $this->driver = $driver;
50
51 1
        $this->table = $table;
52
53 1
        $this->columns = array_filter(
54 1
            $table->listColumns(),
55
            function (Column $column) {
56 1
                return $column->isAuto() === false;
57 1
            }
58
        );
59
60 1
        return $this;
0 ignored issues
show
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
61
    }
62
63
64
    /**
65
     * Add a record to this INSERT query.
66
     *
67
     * @param array $record record map (where Column name => value)
68
     *
69
     * @return $this
70
     */
71 1
    public function add(array $record)
72
    {
73 1
        $placeholders = [];
74
75 1
        $tuple_num = count($this->tuples);
76
77 1
        foreach ($this->columns as $col_index => $column) {
78 1
            $name = $column->getName();
79
80 1
            if (array_key_exists($name, $record)) {
81 1
                $value = $record[$name];
82
            } elseif ($column->isRequired() === false) {
83
                $value = $column->getDefault();
84
            } else {
85
                throw new RuntimeException("required value '{$name}' missing from tuple # {$tuple_num}");
86
            }
87
88 1
            $placeholder = "c{$tuple_num}_{$col_index}";
89
90 1
            $placeholders[] = ":{$placeholder}";
91
92 1
            $this->bind($placeholder, $value, $column->getType());
93
        }
94
95 1
        $this->tuples[] = "(" . implode(", ", $placeholders) . ")";
96
97 1
        return $this;
98
    }
99
100
    /**
101
     * @inheritdoc
102
     */
103 1
    public function getSQL()
104
    {
105 1
        if (count($this->tuples) === 0) {
106
            throw new RuntimeException("no records added to this query");
107
        }
108
109 1
        $table = "{$this->table}";
110
111 1
        $quoted_column_names = implode(
112 1
            ", ",
113
            array_map(
114 1
                function (Column $column) {
115 1
                    return $this->driver->quoteName($column->getName());
116 1
                },
117 1
                $this->columns
118
            )
119
        );
120
121 1
        return "INSERT INTO {$table} ({$quoted_column_names}) VALUES\n" . implode(",\n", $this->tuples);
122
    }
123
}
124