diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index d499e247..2f960300 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -475,6 +475,16 @@ parameters: count: 2 path: src/Statements/CallStatement.php + - + message: "#^Cannot access property \\$database on PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\|null\\.$#" + count: 1 + path: src/Statements/CreateStatement.php + + - + message: "#^Cannot access property \\$table on PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\|null\\.$#" + count: 1 + path: src/Statements/CreateStatement.php + - message: "#^Cannot access property \\$value on PhpMyAdmin\\\\SqlParser\\\\Token\\|null\\.$#" count: 2 @@ -497,7 +507,7 @@ parameters: - message: "#^Cannot call method has\\(\\) on PhpMyAdmin\\\\SqlParser\\\\Components\\\\OptionsArray\\|null\\.$#" - count: 8 + count: 11 path: src/Statements/CreateStatement.php - @@ -505,6 +515,11 @@ parameters: count: 1 path: src/Statements/CreateStatement.php + - + message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, mixed given\\.$#" + count: 2 + path: src/Statements/CreateStatement.php + - message: "#^Property PhpMyAdmin\\\\SqlParser\\\\Statements\\\\CreateStatement\\:\\:\\$fields \\(array\\\\|PhpMyAdmin\\\\SqlParser\\\\Components\\\\ArrayObj\\|null\\) does not accept array\\\\|PhpMyAdmin\\\\SqlParser\\\\Components\\\\ArrayObj\\.$#" count: 1 @@ -875,19 +890,9 @@ parameters: count: 1 path: src/Utils/Query.php - - - message: "#^Cannot access property \\$database on PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\|null\\.$#" - count: 1 - path: src/Utils/Table.php - - - - message: "#^Cannot access property \\$table on PhpMyAdmin\\\\SqlParser\\\\Components\\\\Expression\\|null\\.$#" - count: 1 - path: src/Utils/Table.php - - message: "#^Cannot call method has\\(\\) on PhpMyAdmin\\\\SqlParser\\\\Components\\\\OptionsArray\\|null\\.$#" - count: 4 + count: 1 path: src/Utils/Table.php - @@ -895,11 +900,6 @@ parameters: count: 1 path: src/Utils/Table.php - - - message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, mixed given\\.$#" - count: 2 - path: src/Utils/Table.php - - message: "#^Parameter \\#2 \\$list of static method PhpMyAdmin\\\\SqlParser\\\\Utils\\\\Query\\:\\:replaceClause\\(\\) expects PhpMyAdmin\\\\SqlParser\\\\TokensList, PhpMyAdmin\\\\SqlParser\\\\TokensList\\|null given\\.$#" count: 1 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index fc825eff..aeef4c62 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -679,8 +679,14 @@ + + $field]]> + + + + $field]]> @@ -688,10 +694,16 @@ + + + + parameters]]> + references->table->database]]> + references->table->table]]> value]]> value]]> @@ -713,6 +725,8 @@ + + value]]> @@ -725,6 +739,7 @@ + fields)]]> partitionBy)]]> partitionBy)]]> partitions)]]> @@ -1022,6 +1037,17 @@ + + + + + + + + + + + tokens[$list->idx - 2]->value]]]> @@ -1165,13 +1191,7 @@ - - - - - - @@ -1196,18 +1216,11 @@ - - references->table->database]]> - references->table->table]]> - - - fields)]]> - fields)]]> diff --git a/src/Statements/CreateStatement.php b/src/Statements/CreateStatement.php index 7377b95f..8ce6007b 100644 --- a/src/Statements/CreateStatement.php +++ b/src/Statements/CreateStatement.php @@ -23,8 +23,10 @@ use PhpMyAdmin\SqlParser\Token; use PhpMyAdmin\SqlParser\TokensList; use PhpMyAdmin\SqlParser\TokenType; +use PhpMyAdmin\SqlParser\Utils\ForeignKey; use function is_array; +use function str_replace; use function trim; /** @@ -775,4 +777,55 @@ public function parse(Parser $parser, TokensList $list): void } } } + + /** @return list */ + public function getForeignKeys(): array + { + if (empty($this->fields) || (! is_array($this->fields)) || (! $this->options->has('TABLE'))) { + return []; + } + + $ret = []; + + foreach ($this->fields as $field) { + if ($field->key === null || $field->key->type !== 'FOREIGN KEY') { + continue; + } + + $columns = []; + foreach ($field->key->columns as $column) { + if (! isset($column['name'])) { + continue; + } + + $columns[] = $column['name']; + } + + $foreignKey = new ForeignKey(); + $foreignKey->constraint = $field->name; + $foreignKey->indexList = $columns; + + if ($field->references !== null) { + $foreignKey->refDbName = $field->references->table->database; + $foreignKey->refTableName = $field->references->table->table; + $foreignKey->refIndexList = $field->references->columns; + + $opt = $field->references->options->has('ON UPDATE'); + + if ($opt) { + $foreignKey->onUpdate = str_replace(' ', '_', $opt); + } + + $opt = $field->references->options->has('ON DELETE'); + + if ($opt) { + $foreignKey->onDelete = str_replace(' ', '_', $opt); + } + } + + $ret[] = $foreignKey; + } + + return $ret; + } } diff --git a/src/Utils/ForeignKey.php b/src/Utils/ForeignKey.php new file mode 100644 index 00000000..54e294a0 --- /dev/null +++ b/src/Utils/ForeignKey.php @@ -0,0 +1,23 @@ + - * @psalm-return list - */ - public static function getForeignKeys(CreateStatement $statement): array - { - if (empty($statement->fields) || (! is_array($statement->fields)) || (! $statement->options->has('TABLE'))) { - return []; - } - - $ret = []; - - foreach ($statement->fields as $field) { - if (empty($field->key) || ($field->key->type !== 'FOREIGN KEY')) { - continue; - } - - $columns = []; - foreach ($field->key->columns as $column) { - if (! isset($column['name'])) { - continue; - } - - $columns[] = $column['name']; - } - - $tmp = [ - 'constraint' => $field->name, - 'index_list' => $columns, - ]; - - if (! empty($field->references)) { - $tmp['ref_db_name'] = $field->references->table->database; - $tmp['ref_table_name'] = $field->references->table->table; - $tmp['ref_index_list'] = $field->references->columns; - - $opt = $field->references->options->has('ON UPDATE'); - - if ($opt) { - $tmp['on_update'] = str_replace(' ', '_', $opt); - } - - $opt = $field->references->options->has('ON DELETE'); - - if ($opt) { - $tmp['on_delete'] = str_replace(' ', '_', $opt); - } - } - - $ret[] = $tmp; - } - - return $ret; - } - /** * Gets fields of the table. * diff --git a/tests/Utils/TableTest.php b/tests/Utils/TableTest.php index 40f8303e..c96f55b1 100644 --- a/tests/Utils/TableTest.php +++ b/tests/Utils/TableTest.php @@ -7,43 +7,24 @@ use PhpMyAdmin\SqlParser\Parser; use PhpMyAdmin\SqlParser\Statements\CreateStatement; use PhpMyAdmin\SqlParser\Tests\TestCase; +use PhpMyAdmin\SqlParser\Utils\ForeignKey; use PhpMyAdmin\SqlParser\Utils\Table; use PHPUnit\Framework\Attributes\DataProvider; class TableTest extends TestCase { - /** - * @param array[] $expected - * @psalm-param list $expected - */ + /** @param list $expected */ #[DataProvider('getForeignKeysProvider')] public function testGetForeignKeys(string $query, array $expected): void { $parser = new Parser($query); $this->assertInstanceOf(CreateStatement::class, $parser->statements[0]); - $this->assertEquals($expected, Table::getForeignKeys($parser->statements[0])); + + $result = $parser->statements[0]->getForeignKeys(); + $this->assertEquals($expected, $result); } - /** - * @return array[]>> - * @psalm-return list}> - */ + /** @return list}> */ public static function getForeignKeysProvider(): array { return [ @@ -72,31 +53,28 @@ public static function getForeignKeysProvider(): array REFERENCES `staff` (`staff_id`) ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=16050 DEFAULT CHARSET=utf8', [ - [ - 'constraint' => 'fk_payment_customer', - 'index_list' => ['customer_id'], - 'ref_db_name' => null, - 'ref_table_name' => 'customer', - 'ref_index_list' => ['customer_id'], - 'on_update' => 'CASCADE', - ], - [ - 'constraint' => 'fk_payment_rental', - 'index_list' => ['rental_id'], - 'ref_db_name' => null, - 'ref_table_name' => 'rental', - 'ref_index_list' => ['rental_id'], - 'on_delete' => 'SET_NULL', - 'on_update' => 'CASCADE', - ], - [ - 'constraint' => 'fk_payment_staff', - 'index_list' => ['staff_id'], - 'ref_db_name' => null, - 'ref_table_name' => 'staff', - 'ref_index_list' => ['staff_id'], - 'on_update' => 'CASCADE', - ], + new ForeignKey( + constraint: 'fk_payment_customer', + indexList: ['customer_id'], + refTableName: 'customer', + refIndexList: ['customer_id'], + onUpdate: 'CASCADE', + ), + new ForeignKey( + constraint: 'fk_payment_rental', + indexList: ['rental_id'], + refTableName: 'rental', + refIndexList: ['rental_id'], + onDelete: 'SET_NULL', + onUpdate: 'CASCADE', + ), + new ForeignKey( + constraint: 'fk_payment_staff', + indexList: ['staff_id'], + refTableName: 'staff', + refIndexList: ['staff_id'], + onUpdate: 'CASCADE', + ), ], ], [ @@ -125,14 +103,13 @@ public static function getForeignKeysProvider(): array CONSTRAINT `fk_address_city` FOREIGN KEY (`city_id`) REFERENCES `city` (`city_id`) ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=606 DEFAULT CHARSET=utf8', [ - [ - 'constraint' => 'fk_address_city', - 'index_list' => ['city_id'], - 'ref_db_name' => null, - 'ref_table_name' => 'city', - 'ref_index_list' => ['city_id'], - 'on_update' => 'CASCADE', - ], + new ForeignKey( + constraint: 'fk_address_city', + indexList: ['city_id'], + refTableName: 'city', + refIndexList: ['city_id'], + onUpdate: 'CASCADE', + ), ], ], ];