Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
Create
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
7 / 7
21
100.00% covered (success)
100.00%
1 / 1
 ifNotExists
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setEngine
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getEngine
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setCharset
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getCharset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 render
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
15
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
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;
16
17/**
18 * Schema CREATE table class
19 *
20 * @category   Pop
21 * @package    Pop\Db
22 * @author     Nick Sagona, III <nick@popphp.org>
23 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
24 * @license    https://www.popphp.org/license     New BSD License
25 * @version    7.0.0
26 */
27class Create extends AbstractStructure
28{
29
30    /**
31     * IF NOT EXISTS flag
32     * @var bool
33     */
34    protected bool $ifNotExists = false;
35
36    /**
37     * Table engine (MySQL only)
38     * @var string
39     */
40    protected string $engine = 'InnoDB';
41
42    /**
43     * Table charset (MySQL only)
44     * @var string
45     */
46    protected string $charset = 'utf8';
47
48    /**
49     * Set the IF NOT EXISTS flag
50     *
51     * @return Create
52     */
53    public function ifNotExists(): Create
54    {
55        $this->ifNotExists = true;
56        return $this;
57    }
58
59    /**
60     * Set the table engine (MySQL only)
61     *
62     * @param  string $engine
63     * @return Create
64     */
65    public function setEngine(string $engine): Create
66    {
67        $this->engine = $engine;
68        return $this;
69    }
70
71    /**
72     * Get the table engine (MySQL only)
73     *
74     * @return string
75     */
76    public function getEngine(): string
77    {
78        return $this->engine;
79    }
80
81    /**
82     * Set the table charset (MySQL only)
83     *
84     * @param  string $charset
85     * @return Create
86     */
87    public function setCharset(string $charset): Create
88    {
89        $this->charset = $charset;
90        return $this;
91    }
92
93    /**
94     * Get the table charset (MySQL only)
95     *
96     * @return string
97     */
98    public function getCharset(): string
99    {
100        return $this->charset;
101    }
102
103    /**
104     * Render the table schema
105     *
106     * @return string
107     */
108    public function render(): string
109    {
110        $schema = '';
111
112        // Create PGSQL sequence
113        if (($this->hasIncrement()) && ($this->isPgsql())) {
114            $schema .= Formatter\Table::createPgsqlSequences($this->getIncrement(), $this->table, $this->columns);
115        }
116
117        /*
118         * START CREATE TABLE
119         */
120        $schema .= 'CREATE TABLE ' . ((($this->ifNotExists) && ($this->dbType != self::SQLSRV)) ? 'IF NOT EXISTS ' : null) .
121            $this->quoteId($this->table) . ' (' . PHP_EOL;
122
123        // Iterate over the columns
124        $i         = 0;
125        $increment = null;
126        foreach ($this->columns as $name => $column) {
127            if ($column['increment'] !== false) {
128                $increment = $column['increment'];
129            }
130            $schema .= (($i != 0) ? ',' . PHP_EOL : null) . '  ' . $this->getColumnSchema($name, $column);
131            $i++;
132        }
133
134        // Format primary key schema
135        if ($this->hasPrimary()) {
136            $schema .= Formatter\Table::formatPrimarySchema($this->dbType, $this->getPrimary(true));
137        }
138
139        // SQLite doesn't support adding a FOREIGN KEY constraint via ALTER TABLE, so it has
140        // to be declared inline within the CREATE TABLE statement instead
141        if (($this->isSqlite()) && (count($this->constraints) > 0)) {
142            $schema .= Formatter\Table::formatConstraintsInline($this->constraints, $this);
143        }
144
145        $schema .= Formatter\Table::formatEndOfTable($this->dbType, $this->engine, $this->charset, $increment);
146
147        /*
148         * END CREATE TABLE
149         */
150
151        // Assign PGSQL or SQLITE sequences
152        if ($this->hasIncrement()) {
153            $schema .= Formatter\Table::createSequences(
154                $this->dbType, $this->getIncrement(), $this->quoteId($this->table), $this->columns
155            );
156        }
157
158        // Add indices
159        if (count($this->indices) > 0) {
160            $schema .= Formatter\Table::createIndices($this->indices, $this->table, $this);
161        }
162
163        // Add constraints (already inlined above for SQLite)
164        if ((count($this->constraints) > 0) && (!$this->isSqlite())) {
165            $schema .= Formatter\Table::createConstraints($this->constraints, $this->table, $this);
166        }
167
168        return $schema . PHP_EOL;
169    }
170
171    /**
172     * Render the table schema to string
173     *
174     * @return string
175     */
176    public function __toString(): string
177    {
178        return $this->render();
179    }
180
181}