Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
postgresql_platform
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 11
600
0.00% covered (danger)
0.00%
0 / 1
 getIdentitySequenceName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getIntegerTypeDeclarationSQL
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getBigIntTypeDeclarationSQL
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSmallIntTypeDeclarationSQL
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDefaultValueDeclarationSQL
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 supportsIdentityColumns
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 _getCreateTableSQL
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
 isSerialColumn
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
 isNumericType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
12
 getListSequencesSQL
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getDropIndexSQL
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2/**
3 *
4 * This file is part of the phpBB Forum Software package.
5 *
6 * @copyright (c) phpBB Limited <https://www.phpbb.com>
7 * @license GNU General Public License, version 2 (GPL-2.0)
8 *
9 * For full copyright and license information, please see
10 * the docs/CREDITS.txt file.
11 *
12 */
13
14namespace phpbb\db\doctrine;
15
16use Doctrine\DBAL\Platforms\AbstractPlatform;
17use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
18use Doctrine\DBAL\Schema\Index;
19use Doctrine\DBAL\Schema\Sequence;
20use Doctrine\DBAL\Schema\Table;
21use Doctrine\DBAL\Types\BigIntType;
22use Doctrine\DBAL\Types\IntegerType;
23use Doctrine\DBAL\Types\SmallIntType;
24use Doctrine\DBAL\Types\Type;
25
26/**
27 * PostgreSQL specific schema restrictions for BC.
28 *
29 * Doctrine is using SERIAL which auto creates the sequences with
30 * a name different from the one our driver is using. So in order
31 * to stay compatible with the existing DB we have to change its
32 * naming and not ours.
33 */
34class postgresql_platform extends PostgreSQL94Platform
35{
36    /**
37     * {@inheritdoc}
38     */
39    public function getIdentitySequenceName($tableName, $columnName): string
40    {
41        return $tableName . '_seq';
42    }
43
44    /**
45     * {@inheritDoc}
46     */
47    public function getIntegerTypeDeclarationSQL(array $column): string
48    {
49        return 'INT';
50    }
51
52    /**
53     * {@inheritDoc}
54     */
55    public function getBigIntTypeDeclarationSQL(array $column): string
56    {
57        return 'BIGINT';
58    }
59
60    /**
61     * {@inheritDoc}
62     */
63    public function getSmallIntTypeDeclarationSQL(array $column): string
64    {
65        return 'SMALLINT';
66    }
67
68    /**
69     * {@inheritDoc}
70     */
71    public function getDefaultValueDeclarationSQL($column): string
72    {
73        if ($this->isSerialColumn($column))
74        {
75            return ' DEFAULT {{placeholder_sequence}}';
76        }
77
78        return AbstractPlatform::getDefaultValueDeclarationSQL($column);
79    }
80
81    /**
82     * {@inheritDoc}
83     */
84    public function supportsIdentityColumns(): bool
85    {
86        return false;
87    }
88
89    /**
90     * {@inheritDoc}
91     */
92    protected function _getCreateTableSQL($name, array $columns, array $options = []): array
93    {
94        $sql = [];
95        $post_sql = [];
96        foreach ($columns as $column_name => $column)
97        {
98            if (!empty($column['autoincrement']))
99            {
100                $sequence = new Sequence($this->getIdentitySequenceName($name, $column_name));
101                $sql[] = $this->getCreateSequenceSQL($sequence);
102                $post_sql[] = 'ALTER SEQUENCE '.$sequence->getName().' OWNED BY '.$name.'.'.$column_name;
103            }
104        }
105        $sql = array_merge($sql, parent::_getCreateTableSQL($name, $columns, $options), $post_sql);
106
107        foreach ($sql as $i => $query)
108        {
109            $sql[$i] = str_replace('{{placeholder_sequence}}', "nextval('{$name}_seq')", $query);
110        }
111
112        return $sql;
113    }
114
115    /**
116     * Return if column is a "serial" column, i.e. type supporting auto-increment
117     *
118     * @param array $column Column data
119     * @return bool
120     */
121    private function isSerialColumn(array $column): bool
122    {
123        return isset($column['type'], $column['autoincrement'])
124            && $column['autoincrement'] === true
125            && $this->isNumericType($column['type']);
126    }
127
128    /**
129     * Return if supplied type is of numeric type
130     *
131     * @param Type $type
132     * @return bool
133     */
134    private function isNumericType(Type $type): bool
135    {
136        return $type instanceof IntegerType || $type instanceof BigIntType || $type instanceof SmallIntType;
137    }
138
139    /**
140     * {@inheritDoc}
141     */
142    public function getListSequencesSQL($database): string
143    {
144        return "SELECT sequence_name AS relname,
145                sequence_schema AS schemaname,
146                1 AS min_value,
147                1 AS increment_by
148            FROM information_schema.sequences
149            WHERE sequence_schema NOT LIKE 'pg\_%'
150                AND sequence_schema <> 'information_schema'";
151    }
152
153    /**
154     * {@inheritDoc}
155     */
156    public function getDropIndexSQL($index, $table = null): string
157    {
158        // If we have a primary or a unique index, we need to drop the constraint
159        // instead of the index itself or postgreSQL will reject the query.
160        if ($index instanceof Index)
161        {
162            if ($index->isPrimary())
163            {
164                if ($table instanceof Table)
165                {
166                    $table = $table->getQuotedName($this);
167                }
168                else if (!is_string($table))
169                {
170                    throw new \InvalidArgumentException(
171                        __METHOD__ . '() expects $table parameter to be string or ' . Table::class . '.'
172                    );
173                }
174
175                return 'ALTER TABLE '.$table.' DROP CONSTRAINT '.$index->getQuotedName($this);
176            }
177        }
178        else if (! is_string($index))
179        {
180            throw new \InvalidArgumentException(
181                __METHOD__ . '() expects $index parameter to be string or ' . Index::class . '.'
182            );
183        }
184
185        return parent::getDropIndexSQL($index, $table);
186    }
187}