From bc17bccda57a7eb0f30d1c0561283ecff22c0d45 Mon Sep 17 00:00:00 2001 From: Angel Date: Sat, 26 Jun 2021 10:58:49 +0800 Subject: [PATCH] [fix] Fix column and table name with single character only #981 #983 --- src/Medoo.php | 22 +++++++++++----------- tests/MedooTestCase.php | 2 +- tests/SelectTest.php | 25 +++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/Medoo.php b/src/Medoo.php index d3bed074..3d94e76d 100644 --- a/src/Medoo.php +++ b/src/Medoo.php @@ -595,7 +595,7 @@ protected function generate(string $statement, array $map): string ]; $statement = preg_replace( - '/(?!\'[^\s]+\s?)"([\p{L}_][\p{L}\p{N}@$#\-_]+)"(?!\s?[^\s]+\')/u', + '/(?!\'[^\s]+\s?)"([\p{L}_][\p{L}\p{N}@$#\-_]*)"(?!\s?[^\s]+\')/u', $identifier[$this->type] ?? '"$1"', $statement ); @@ -659,7 +659,7 @@ protected function buildRaw($raw, array &$map): ?string } $query = preg_replace_callback( - '/(([`\']).*?)?((FROM|TABLE|INTO|UPDATE|JOIN)\s*)?\<(([\p{L}_][\p{L}\p{N}@$#\-_]+)(\.[\p{L}_][\p{L}\p{N}@$#\-_]+)?)\>([^,]*?\2)?/u', + '/(([`\']).*?)?((FROM|TABLE|INTO|UPDATE|JOIN)\s*)?\<(([\p{L}_][\p{L}\p{N}@$#\-_]*)(\.[\p{L}_][\p{L}\p{N}@$#\-_]*)?)\>([^,]*?\2)?/u', function ($matches) { if (!empty($matches[2]) && isset($matches[8])) { return $matches[0]; @@ -708,7 +708,7 @@ public function quote(string $string): string */ public function tableQuote(string $table): string { - if (preg_match('/^[\p{L}_][\p{L}\p{N}@$#\-_]+$/u', $table)) { + if (preg_match('/^[\p{L}_][\p{L}\p{N}@$#\-_]*$/u', $table)) { return '"' . $this->prefix . $table . '"'; } @@ -723,7 +723,7 @@ public function tableQuote(string $table): string */ public function columnQuote(string $column): string { - if (preg_match('/^[\p{L}_][\p{L}\p{N}@$#\-_]+(\.?[\p{L}_][\p{L}\p{N}@$#\-_]+)?$/u', $column)) { + if (preg_match('/^[\p{L}_][\p{L}\p{N}@$#\-_]*(\.?[\p{L}_][\p{L}\p{N}@$#\-_]*)?$/u', $column)) { return strpos($column, '.') !== false ? '"' . $this->prefix . str_replace('.', '"."', $column) . '"' : '"' . $column . '"'; @@ -1168,7 +1168,7 @@ protected function selectContext( array $where = null, $columnFn = null ): string { - preg_match('/(?[\p{L}_][\p{L}\p{N}@$#\-_]+)\s*\((?[\p{L}_][\p{L}\p{N}@$#\-_]+)\)/u', $table, $tableMatch); + preg_match('/(?
[\p{L}_][\p{L}\p{N}@$#\-_]*)\s*\((?[\p{L}_][\p{L}\p{N}@$#\-_]*)\)/u', $table, $tableMatch); if (isset($tableMatch['table'], $tableMatch['alias'])) { $table = $this->tableQuote($tableMatch['table']); @@ -1269,7 +1269,7 @@ protected function buildJoin(string $table, array $join, array &$map): string ]; foreach ($join as $subtable => $relation) { - preg_match('/(\[(?\<\>?|\>\[\p{L}_][\p{L}\p{N}@$#\-_]+)\s?(\((?[\p{L}_][\p{L}\p{N}@$#\-_]+)\))?/u', $subtable, $match); + preg_match('/(\[(?\<\>?|\>\[\p{L}_][\p{L}\p{N}@$#\-_]*)\s?(\((?[\p{L}_][\p{L}\p{N}@$#\-_]*)\))?/u', $subtable, $match); if ($match['join'] === '' || $match['table'] === '') { continue; @@ -1336,7 +1336,7 @@ protected function columnMap($columns, array &$stack, bool $root): array foreach ($columns as $key => $value) { if (is_int($key)) { - preg_match('/([\p{L}_][\p{L}\p{N}@$#\-_]+\.)?(?[\p{L}_][\p{L}\p{N}@$#\-_]+)(?:\s*\((?[\p{L}_][\p{L}\p{N}@$#\-_]+)\))?(?:\s*\[(?(?:String|Bool|Int|Number|Object|JSON))\])?/u', $value, $keyMatch); + preg_match('/([\p{L}_][\p{L}\p{N}@$#\-_]*\.)?(?[\p{L}_][\p{L}\p{N}@$#\-_]*)(?:\s*\((?[\p{L}_][\p{L}\p{N}@$#\-_]*)\))?(?:\s*\[(?(?:String|Bool|Int|Number|Object|JSON))\])?/u', $value, $keyMatch); $columnKey = !empty($keyMatch['alias']) ? $keyMatch['alias'] : @@ -1346,7 +1346,7 @@ protected function columnMap($columns, array &$stack, bool $root): array [$columnKey, $keyMatch['type']] : [$columnKey, 'String']; } elseif ($this->isRaw($value)) { - preg_match('/([\p{L}_][\p{L}\p{N}@$#\-_]+\.)?(?[\p{L}_][\p{L}\p{N}@$#\-_]+)(\s*\[(?(String|Bool|Int|Number))\])?/u', $key, $keyMatch); + preg_match('/([\p{L}_][\p{L}\p{N}@$#\-_]*\.)?(?[\p{L}_][\p{L}\p{N}@$#\-_]*)(\s*\[(?(String|Bool|Int|Number))\])?/u', $key, $keyMatch); $columnKey = $keyMatch['column']; $stack[$key] = isset($keyMatch['type']) ? @@ -1389,7 +1389,7 @@ protected function dataMap( if (count($columnsKey) === 1 && is_array($columns[$columnsKey[0]])) { $indexKey = array_keys($columns)[0]; - $dataKey = preg_replace("/^[\p{L}_][\p{L}\p{N}@$#\-_]+\./u", '', $indexKey); + $dataKey = preg_replace("/^[\p{L}_][\p{L}\p{N}@$#\-_]*\./u", '', $indexKey); $currentStack = []; foreach ($data as $item) { @@ -1523,7 +1523,7 @@ public function create(string $table, $columns, $options = null): ?PDOStatement foreach ($columns as $name => $definition) { if (is_int($name)) { - $stack[] = preg_replace('/\<([\p{L}_][\p{L}\p{N}@$#\-_]+)\>/u', '"$1"', $definition); + $stack[] = preg_replace('/\<([\p{L}_][\p{L}\p{N}@$#\-_]*)\>/u', '"$1"', $definition); } elseif (is_array($definition)) { $stack[] = $this->columnQuote($name) . ' ' . implode(' ', $definition); } elseif (is_string($definition)) { @@ -1778,7 +1778,7 @@ public function update(string $table, $data, $where = null): ?PDOStatement continue; } - preg_match('/(?[\p{L}_][\p{L}\p{N}@$#\-_]+)(\[(?\+|\-|\*|\/)\])?/u', $key, $match); + preg_match('/(?[\p{L}_][\p{L}\p{N}@$#\-_]*)(\[(?\+|\-|\*|\/)\])?/u', $key, $match); if (isset($match['operator'])) { if (is_numeric($value)) { diff --git a/tests/MedooTestCase.php b/tests/MedooTestCase.php index 4c7c40b0..1fae4d7b 100644 --- a/tests/MedooTestCase.php +++ b/tests/MedooTestCase.php @@ -40,7 +40,7 @@ public function expectedQuery($expected): string ]; return preg_replace( - '/(?!\'[^\s]+\s?)"((?![_\d])[\p{N}\p{L}\-_]+)"(?!\s?[^\s]+\')/u', + '/(?!\'[^\s]+\s?)"([\p{L}_][\p{L}\p{N}@$#\-_]*)"(?!\s?[^\s]+\')/u', $identifier[$this->database->type] ?? '"$1"', str_replace("\n", " ", $expected) ); diff --git a/tests/SelectTest.php b/tests/SelectTest.php index 1bd321c6..7da61586 100644 --- a/tests/SelectTest.php +++ b/tests/SelectTest.php @@ -687,4 +687,29 @@ public function testSelectWithHyphenCharacter($type) $this->database->queryString ); } + + /** + * @covers ::columnMap() + * @covers ::columnPush() + * @dataProvider typesProvider + */ + public function testSelectWithSingleCharacter($type) + { + $this->setType($type); + + $this->database->select("a", [ + "[>]e" => ["f"] + ], [ + "b (c)" + ]); + + $this->assertQuery( + <<database->queryString + ); + } }