Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
58.18% covered (warning)
58.18%
32 / 55
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
MysqlGrammar
58.18% covered (warning)
58.18%
32 / 55
50.00% covered (danger)
50.00%
3 / 6
66.12
0.00% covered (danger)
0.00%
0 / 1
 compilePostQueries
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
56
 compileAlterRemove
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 compileSelectTables
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 compileSelectFields
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 compileCreateFields
90.91% covered (success)
90.91%
20 / 22
0.00% covered (danger)
0.00%
0 / 1
12.11
 compileCreateTableSettings
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   phpOMS\DataStorage\Database\Schema\Grammar
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace phpOMS\DataStorage\Database\Schema\Grammar;
16
17use phpOMS\DataStorage\Database\BuilderAbstract;
18use phpOMS\DataStorage\Database\Query\Builder;
19use phpOMS\DataStorage\Database\Schema\Builder as SchemaBuilder;
20use phpOMS\DataStorage\Database\Schema\QueryType;
21
22/**
23 * Database query grammar.
24 *
25 * @package phpOMS\DataStorage\Database\Schema\Grammar
26 * @license OMS License 2.0
27 * @link    https://jingga.app
28 * @since   1.0.0
29 */
30class MysqlGrammar extends Grammar
31{
32    /**
33     * System identifier.
34     *
35     * @var string
36     * @since 1.0.0
37     */
38    public string $systemIdentifierStart = '`';
39
40    /**
41     * System identifier.
42     *
43     * @var string
44     * @since 1.0.0
45     */
46    public string $systemIdentifierEnd = '`';
47
48    /**
49     * {@inheritdoc}
50     */
51    public function compilePostQueries(BuilderAbstract $query) : array
52    {
53        /** @var SchemaBuilder $query */
54
55        $sql = [];
56        switch ($query->getType()) {
57            case QueryType::CREATE_TABLE:
58                foreach ($query->createFields as $name => $field) {
59                    if (isset($field['meta']['multi_autoincrement'])) {
60                        $tmpSql = 'CREATE TRIGGER update_' . $name
61                            . ' BEFORE INSERT ON ' . $query->createTable
62                            . ' FOR EACH ROW BEGIN'
63                            . ' SET NEW.' . $name . ' = ('
64                                . 'SELECT COALESCE(MAX(' . $name . '), 0) + 1'
65                                . ' FROM ' . $query->createTable
66                                . ' WHERE';
67
68                        foreach ($field['meta']['multi_autoincrement'] as $index => $autoincrement) {
69                            $tmpSql .= ($index > 0 ? ' AND' : '') . ' ' . $autoincrement . ' = NEW.' . $autoincrement;
70                        }
71
72                        $tmpSql .= ' LIMIT 1); END;';
73
74                        $sql[] = $tmpSql;
75                    }
76                }
77
78                break;
79            default:
80                return [];
81        }
82
83        return $sql;
84    }
85
86    /**
87     * Compile remove
88     *
89     * @param Builder $query  Builder
90     * @param array   $remove Remove data
91     *
92     * @return string
93     *
94     * @since 1.0.0
95     */
96    protected function compileAlterRemove(BuilderAbstract $query, array $remove) : string
97    {
98        $keyWord = $remove['type'] === 'CONSTRAINT' ? 'FOREIGN KEY ' : 'COLUMN';
99
100        return 'DROP ' . $keyWord . ' ' . $remove['identifier'];
101    }
102
103    /**
104     * Compile from.
105     *
106     * @param SchemaBuilder $query Builder
107     * @param array         $table Tables
108     *
109     * @return string
110     *
111     * @since 1.0.0
112     */
113    protected function compileSelectTables(SchemaBuilder $query, array $table) : string
114    {
115        $builder = new Builder($query->getConnection());
116        $builder->select('table_name')
117            ->from('information_schema.tables')
118            ->where('table_schema', '=', $query->getConnection()->getDatabase());
119
120        return \rtrim($builder->toSql(), ';');
121    }
122
123    /**
124     * Compile from.
125     *
126     * @param SchemaBuilder $query Builder
127     * @param string        $table Tables
128     *
129     * @return string
130     *
131     * @since 1.0.0
132     */
133    protected function compileSelectFields(SchemaBuilder $query, string $table) : string
134    {
135        $builder = new Builder($query->getConnection());
136        $builder->select('*')
137            ->from('information_schema.columns')
138            ->where('table_schema', '=', $query->getConnection()->getDatabase())
139            ->andWhere('table_name', '=', $table);
140
141        return \rtrim($builder->toSql(), ';');
142    }
143
144    /**
145     * Compile create table fields query.
146     *
147     * @param SchemaBuilder $query  Query
148     * @param array         $fields Fields to create
149     *
150     * @return string
151     *
152     * @since 1.0.0
153     */
154    protected function compileCreateFields(SchemaBuilder $query, array $fields) : string
155    {
156        $fieldQuery = '';
157        $keys       = '';
158
159        foreach ($fields as $name => $field) {
160            $fieldQuery .= ' ' . $this->expressionizeTableColumn([$name]) . ' ' . $field['type'];
161
162            if (isset($field['default']) || ($field['default'] === null && ($field['null'] ?? false))) {
163                $fieldQuery .= ' DEFAULT ' . $this->compileValue($query, $field['default']);
164            }
165
166            if ($field['null'] ?? false) {
167                $fieldQuery .= ' ' . ($field['null'] ? '' : 'NOT ') . 'NULL';
168            }
169
170            if ($field['autoincrement'] ?? false) {
171                $fieldQuery .= ' AUTO_INCREMENT';
172            }
173
174            $fieldQuery .= ',';
175
176            if ($field['primary'] ?? false) {
177                $keys .= ' PRIMARY KEY (' .  $this->expressionizeTableColumn([$name]) . '),';
178            }
179
180            if ($field['unique'] ?? false) {
181                $keys .= ' UNIQUE KEY (' .  $this->expressionizeTableColumn([$name]) . '),';
182            }
183
184            if (isset($field['foreignTable'], $field['foreignKey'])) {
185                $keys .= ' FOREIGN KEY (' .  $this->expressionizeTableColumn([$name]) . ') REFERENCES '
186                    . $this->expressionizeTableColumn([$field['foreignTable']])
187                    . ' (' . $this->expressionizeTableColumn([$field['foreignKey']]) . '),';
188            }
189
190            if (isset($field['meta']['multi_autoincrement'])) {
191                $query->hasPostQuery = true;
192            }
193        }
194
195        return '(' . \ltrim(\rtrim($fieldQuery . $keys, ','), ' ') . ')';
196    }
197
198    /**
199     * Compile create table settings query.
200     *
201     * @param BuilderAbstract $query    Query
202     * @param bool            $settings Has settings
203     *
204     * @return string
205     *
206     * @since 1.0.0
207     */
208    protected function compileCreateTableSettings(BuilderAbstract $query, bool $settings) : string
209    {
210        return 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1';
211    }
212}