Completed
Push — master ( 679720...a86c7c )
by Rasmus
08:32
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.0072

Importance

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