Completed
Branch feature/pre-split (57df1d)
by Anton
10:42
created

AbstractIndex::unique()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\Database\Schemas\Prototypes;
8
9
use Spiral\Database\Entities\Driver;
10
use Spiral\Database\Schemas\IndexInterface;
11
12
/**
13
 * Abstract index schema with read (see IndexInterface) and write abilities. Must be implemented
14
 * by driver to support DBMS specific syntax and creation rules.
15
 */
16
abstract class AbstractIndex extends AbstractElement implements IndexInterface
17
{
18
    /**
19
     * Index types.
20
     */
21
    const NORMAL = 'INDEX';
22
    const UNIQUE = 'UNIQUE';
23
24
    /**
25
     * Index type, by default NORMAL and UNIQUE indexes supported, additional types can be
26
     * implemented on database driver level.
27
     *
28
     * @var string
29
     */
30
    protected $type = self::NORMAL;
31
32
    /**
33
     * Columns used to form index.
34
     *
35
     * @var array
36
     */
37
    protected $columns = [];
38
39
    /**
40
     * {@inheritdoc}
41
     */
42
    public function getName(): string
43
    {
44
        if (empty($this->name)) {
45
            //Let's generate index name on a fly
46
            $this->setName($this->generateName());
47
        }
48
49
        return parent::getName();
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function isUnique(): bool
56
    {
57
        return $this->type == self::UNIQUE;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function getColumns(): array
64
    {
65
        return $this->columns;
66
    }
67
68
    /**
69
     * Declare index type and behaviour to unique/non-unique state.
70
     *
71
     * @param bool $unique
72
     *
73
     * @return self
74
     */
75
    public function unique(bool $unique = true): AbstractIndex
76
    {
77
        $this->type = $unique ? self::UNIQUE : self::NORMAL;
78
79
        return $this;
80
    }
81
82
    /**
83
     * Change set of index forming columns. Method must support both array and string parameters.
84
     *
85
     * Example:
86
     * $index->columns('key');
87
     * $index->columns('key', 'key2');
88
     * $index->columns(['key', 'key2']);
89
     *
90
     * @param string|array $columns Columns array or comma separated list of parameters.
91
     *
92
     * @return self
93
     */
94
    public function columns($columns): AbstractIndex
95
    {
96
        if (!is_array($columns)) {
97
            $columns = func_get_args();
98
        }
99
100
        $this->columns = $columns;
101
102
        return $this;
103
    }
104
105
    /**
106
     * Index sql creation syntax.
107
     *
108
     * @param Driver $driver
109
     * @param bool   $includeTable Include table ON statement (not required for inline index
110
     *                             creation).
111
     *
112
     * @return string
113
     */
114
    public function sqlStatement(Driver $driver, bool $includeTable = true): string
115
    {
116
        $statement = [$this->type == self::UNIQUE ? 'UNIQUE INDEX' : 'INDEX'];
117
118
        $statement[] = $driver->identifier($this->name);
119
120
        if ($includeTable) {
121
            $statement[] = "ON {$driver->identifier($this->table)}";
122
        }
123
124
        //Wrapping column names
125
        $columns = implode(', ', array_map([$driver, 'identifier'], $this->columns));
126
127
        $statement[] = "({$columns})";
128
129
        return implode(' ', $statement);
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135
    public function compare(IndexInterface $initial): bool
136
    {
137
        return $this == clone $initial;
138
    }
139
140
    /**
141
     * Generate unique index name.
142
     *
143
     * @return string
144
     */
145
    protected function generateName(): string
146
    {
147
        //We can generate name
148
        $name = $this->table . '_index_' . implode('_', $this->columns) . '_' . uniqid();
149
150
        if (strlen($name) > 64) {
151
            //Many dbs has limitations on identifier length
152
            $name = md5($name);
153
        }
154
155
        return $name;
156
    }
157
}