Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
63 / 63
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
Table
100.00% covered (success)
100.00%
63 / 63
100.00% covered (success)
100.00%
7 / 7
25
100.00% covered (success)
100.00%
1 / 1
 createPgsqlSequences
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 formatPrimarySchema
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 formatEndOfTable
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
5
 createSequences
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
6
 createIndices
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 formatConstraintsInline
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 createConstraints
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Db\Sql\Schema\Formatter;
16
17use Pop\Db\Sql;
18use Pop\Db\Sql\Schema\AbstractStructure;
19
20/**
21 * Schema table formatter class
22 *
23 * @category   Pop
24 * @package    Pop\Db
25 * @author     Nick Sagona, III <nick@popphp.org>
26 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
27 * @license    https://www.popphp.org/license     New BSD License
28 * @version    7.0.0
29 */
30class Table extends AbstractFormatter
31{
32
33    /**
34     * Create PostgreSQL sequences
35     *
36     * @param  array  $increment
37     * @param  string $table
38     * @param  array  $columns
39     * @return string
40     */
41    public static function createPgsqlSequences(array $increment, string $table, array $columns): string
42    {
43        $sequences = '';
44
45        foreach ($increment as $name) {
46            $sequences .= 'CREATE SEQUENCE ' . $table . '_' . $name . '_seq START ' .
47                (int)$columns[$name]['increment'] . ';' . PHP_EOL;
48        }
49
50        return $sequences . PHP_EOL;
51    }
52
53    /**
54     * Format primary key schema
55     *
56     * @param  string $dbType
57     * @param  array  $primary
58     * @return string
59     */
60    public static function formatPrimarySchema(string $dbType, array $primary): string
61    {
62        $primarySchema = '';
63
64        if ($dbType != Sql::SQLSRV) {
65            $primarySchema .= ($dbType == Sql::SQLITE) ?
66                ',' . PHP_EOL . '  UNIQUE (' . implode(', ', $primary) . ')' :
67                ',' . PHP_EOL . '  PRIMARY KEY (' . implode(', ', $primary) . ')';
68        }
69
70        return $primarySchema;
71    }
72
73    /**
74     * Format end of table
75     *
76     * @param  string  $dbType
77     * @param  ?string $engine
78     * @param  ?string $charset
79     * @param  ?int    $increment
80     * @return string
81     */
82    public static function formatEndOfTable(string $dbType, ?string $engine = null, ?string $charset = null, ?int $increment = null): string
83    {
84        $sql = PHP_EOL . ')';
85
86        if ($dbType == Sql::MYSQL) {
87            if ($engine !== null) {
88                $sql .= ' ENGINE=' . $engine;
89            }
90            if ($charset !== null) {
91                $sql .= ' DEFAULT CHARSET=' . $charset;
92            }
93            if ($increment !== null) {
94                $sql .= ' AUTO_INCREMENT=' . (int)$increment;
95            }
96            $sql .= ';' . PHP_EOL . PHP_EOL;
97        } else {
98            $sql .= ';' . PHP_EOL . PHP_EOL;
99        }
100
101        return $sql;
102    }
103
104    /**
105     * Create sequences
106     *
107     * @param  string $dbType
108     * @param  array  $increment
109     * @param  string $table
110     * @param  array  $columns
111     * @return string
112     */
113    public static function createSequences(string $dbType, array $increment, string $table, array $columns): string
114    {
115        $sequences = '';
116
117        if ($dbType == Sql::PGSQL) {
118            foreach ($increment as $name) {
119                $sequences .= 'ALTER SEQUENCE ' . self::unquoteId($table) . '_' . $name . '_seq OWNED BY ' .
120                    $table . '."' . $name . '";' . PHP_EOL;
121            }
122            $sequences .= PHP_EOL;
123        } else if ($dbType == Sql::SQLITE) {
124            foreach ($increment as $name) {
125                $start = (int)$columns[$name]['increment'];
126                if (substr((string)$start, -1) == '1') {
127                    $start -= 1;
128                }
129                $sequences .= 'INSERT INTO "sqlite_sequence" ("name", "seq") ' .
130                    'VALUES (' . $table . ', ' . $start . ');' . PHP_EOL;
131            }
132            $sequences .= PHP_EOL;
133        }
134
135        return $sequences;
136    }
137
138    /**
139     * Create indices
140     *
141     * @param  array             $indices
142     * @param  string            $table
143     * @param  AbstractStructure $schema
144     * @return string
145     */
146    public static function createIndices(array $indices, string $table, AbstractStructure $schema): string
147    {
148        $indexSchema = '';
149
150        foreach ($indices as $name => $index) {
151            foreach ($index['column'] as $i => $column) {
152                $index['column'][$i] = $schema->quoteId($column);
153            }
154
155            if ($index['type'] != 'primary') {
156                $indexSchema .= 'CREATE ' . (($index['type'] == 'unique') ? 'UNIQUE ' : null) . 'INDEX ' .
157                    $schema->quoteId($name) . ' ON ' . $schema->quoteId($table) .
158                    ' (' . implode(', ', $index['column']) . ');' . PHP_EOL;
159            }
160        }
161
162        return $indexSchema;
163    }
164
165    /**
166     * Format constraints inline within the CREATE TABLE statement (SQLite only - it does not
167     * support adding a FOREIGN KEY constraint to a table via ALTER TABLE)
168     *
169     * @param  array             $constraints
170     * @param  AbstractStructure $schema
171     * @return string
172     */
173    public static function formatConstraintsInline(array $constraints, AbstractStructure $schema): string
174    {
175        $constraintSchema = '';
176
177        foreach ($constraints as $name => $constraint) {
178            $constraintSchema .= ',' . PHP_EOL . '  CONSTRAINT ' . $schema->quoteId($name) .
179                ' FOREIGN KEY (' . $schema->quoteId($constraint['column']) . ')' .
180                ' REFERENCES ' . $schema->quoteId($constraint['references']) .
181                ' (' . $schema->quoteId($constraint['on']) . ')' . ' ON DELETE ' .
182                $constraint['delete'] . ' ON UPDATE CASCADE';
183        }
184
185        return $constraintSchema;
186    }
187
188    /**
189     * Create constraints
190     *
191     * @param  array             $constraints
192     * @param  string            $table
193     * @param  AbstractStructure $schema
194     * @return string
195     */
196    public static function createConstraints(array $constraints, string $table, AbstractStructure $schema): string
197    {
198        $constraintSchema = PHP_EOL;
199
200        foreach ($constraints as $name => $constraint) {
201            $constraintSchema .= 'ALTER TABLE ' . $schema->quoteId($table) .
202                ' ADD CONSTRAINT ' . $schema->quoteId($name) .
203                ' FOREIGN KEY (' . $schema->quoteId($constraint['column']) . ')' .
204                ' REFERENCES ' . $schema->quoteId($constraint['references']) .
205                ' (' . $schema->quoteId($constraint['on']) . ')' . ' ON DELETE ' .
206                $constraint['delete'] . ' ON UPDATE CASCADE;' . PHP_EOL;
207        }
208
209        return $constraintSchema;
210    }
211
212}