Test Failed
Pull Request — master (#176)
by
unknown
03:27
created

PartitionDefinition::build()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 0
cts 10
cp 0
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 4
nop 2
crap 30
1
<?php
2
3
/**
4
 * Parses the create definition of a partition.
5
 *
6
 * Used for parsing `CREATE TABLE` statement.
7
 */
8
9
namespace PhpMyAdmin\SqlParser\Components;
10
11
use PhpMyAdmin\SqlParser\Component;
12
use PhpMyAdmin\SqlParser\Parser;
13
use PhpMyAdmin\SqlParser\Token;
14
use PhpMyAdmin\SqlParser\TokensList;
15
16
/**
17
 * Parses the create definition of a partition.
18
 *
19
 * Used for parsing `CREATE TABLE` statement.
20
 *
21
 * @category   Components
22
 *
23
 * @license    https://www.gnu.org/licenses/gpl-2.0.txt GPL-2.0+
24
 */
25
class PartitionDefinition extends Component
26
{
27
    /**
28
     * All field options.
29
     *
30
     * @var array
31
     */
32
    public static $OPTIONS = array(
33
        'STORAGE ENGINE' => array(1, 'var'),
34
        'ENGINE' => array(1, 'var'),
35
        'COMMENT' => array(2, 'var'),
36
        'DATA DIRECTORY' => array(3, 'var'),
37
        'INDEX DIRECTORY' => array(4, 'var'),
38
        'MAX_ROWS' => array(5, 'var'),
39
        'MIN_ROWS' => array(6, 'var'),
40
        'TABLESPACE' => array(7, 'var'),
41
        'NODEGROUP' => array(8, 'var'),
42
    );
43
44
    /**
45
     * Whether this entry is a subpartition or a partition.
46
     *
47
     * @var bool
48
     */
49
    public $isSubpartition;
50
51
    /**
52
     * The name of this partition.
53
     *
54
     * @var string
55
     */
56
    public $name;
57
58
    /**
59
     * The type of this partition (what follows the `VALUES` keyword).
60
     *
61
     * @var string
62
     */
63
    public $type;
64
65
    /**
66
     * The expression used to defined this partition.
67
     *
68
     * @var Expression|string
69
     */
70
    public $expr;
71
72
    /**
73
     * The subpartitions of this partition.
74
     *
75
     * @var PartitionDefinition[]
76
     */
77
    public $subpartitions;
78
79
    /**
80
     * The options of this field.
81
     *
82
     * @var OptionsArray
83
     */
84
    public $options;
85
86
    /**
87
     * @param Parser     $parser  the parser that serves as context
88
     * @param TokensList $list    the list of tokens that are being parsed
89
     * @param array      $options parameters for parsing
90
     *
91
     * @return PartitionDefinition
92
     */
93 1
    public static function parse(Parser $parser, TokensList $list, array $options = array())
94
    {
95 1
        $ret = new self();
96
97
        /**
98
         * The state of the parser.
99
         *
100
         * Below are the states of the parser.
101
         *
102
         *      0 -------------[ PARTITION | SUBPARTITION ]------------> 1
103
         *
104
         *      1 -----------------------[ name ]----------------------> 2
105
         *
106
         *      2 ----------------------[ VALUES ]---------------------> 3
107
         *
108
         *      3 ---------------------[ LESS THAN ]-------------------> 4
109
         *      3 ------------------------[ IN ]-----------------------> 4
110
         *
111
         *      4 -----------------------[ expr ]----------------------> 5
112
         *
113
         *      5 ----------------------[ options ]--------------------> 6
114
         *
115
         *      6 ------------------[ subpartitions ]------------------> (END)
116
         *
117
         * @var int
118
         */
119 1
        $state = 0;
120
121 1
        for (; $list->idx < $list->count; ++$list->idx) {
122
            /**
123
             * Token parsed at this moment.
124
             *
125
             * @var Token
126
             */
127 1
            $token = $list->tokens[$list->idx];
128
129
            // End of statement.
130 1
            if ($token->type === Token::TYPE_DELIMITER) {
131 1
                break;
132
            }
133
134
            // Skipping whitespaces and comments.
135 1
            if (($token->type === Token::TYPE_WHITESPACE) || ($token->type === Token::TYPE_COMMENT)) {
136 1
                continue;
137
            }
138
139 1
            if ($state === 0) {
140 1
                $ret->isSubpartition = ($token->type === Token::TYPE_KEYWORD) && ($token->keyword === 'SUBPARTITION');
141 1
                $state = 1;
142 1
            } elseif ($state === 1) {
143 1
                $ret->name = $token->value;
144
145
                // Looking ahead for a 'VALUES' keyword.
146 1
                $idx = $list->idx;
147 1
                $list->getNext();
148 1
                $nextToken = $list->getNext();
149 1
                $list->idx = $idx;
150
151 1
                $state = ($nextToken->type === Token::TYPE_KEYWORD)
152 1
                    && ($nextToken->value === 'VALUES')
153 1
                    ? 2 : 5;
154 1
            } elseif ($state === 2) {
155 1
                $state = 3;
156 1
            } elseif ($state === 3) {
157 1
                $ret->type = $token->value;
158 1
                $state = 4;
159 1 View Code Duplication
            } elseif ($state === 4) {
160 1
                if ($token->value === 'MAXVALUE') {
161
                    $ret->expr = $token->value;
162
                } else {
163 1
                    $ret->expr = Expression::parse(
164 1
                        $parser,
165 1
                        $list,
166
                        array(
167 1
                            'parenthesesDelimited' => true,
168
                            'breakOnAlias' => true,
169
                        )
170
                    );
171
                }
172 1
                $state = 5;
173
            } elseif ($state === 5) {
174
                $ret->options = OptionsArray::parse($parser, $list, static::$OPTIONS);
175
                $state = 6;
176
            } elseif ($state === 6) {
177
                if (($token->type === Token::TYPE_OPERATOR) && ($token->value === '(')) {
178
                    $ret->subpartitions = ArrayObj::parse(
0 ignored issues
show
Documentation Bug introduced by
It seems like \PhpMyAdmin\SqlParser\Co...\PartitionDefinition')) can also be of type object<PhpMyAdmin\SqlParser\Components\ArrayObj>. However, the property $subpartitions is declared as type array<integer,object<Php...s\PartitionDefinition>>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
179
                        $parser,
180
                        $list,
181
                        array(
182
                            'type' => 'PhpMyAdmin\\SqlParser\\Components\\PartitionDefinition',
183
                        )
184
                    );
185
                    ++$list->idx;
186
                }
187
                break;
188
            }
189
        }
190
191 1
        --$list->idx;
192
193 1
        return $ret;
194
    }
195
196
    /**
197
     * @param PartitionDefinition|PartitionDefinition[] $component the component to be built
198
     * @param array                                     $options   parameters for building
199
     *
200
     * @return string
201
     */
202
    public static function build($component, array $options = array())
203
    {
204
        if (is_array($component)) {
205
            return "(\n" . implode(",\n", $component) . "\n)";
206
        }
207
208
        if ($component->isSubpartition) {
209
            return trim('SUBPARTITION ' . $component->name . ' ' . $component->options);
210
        }
211
212
        $subpartitions = empty($component->subpartitions) ? '' : ' ' . self::build($component->subpartitions);
213
214
        return trim(
215
            'PARTITION ' . $component->name
216
            . (empty($component->type) ? '' : ' VALUES ' . $component->type . ' ' . $component->expr . ' ')
217
            . $component->options . $subpartitions
218
        );
219
    }
220
}
221