Skip to content

Commit 93b9b29

Browse files
committed
Support comma as decimal separator in SI value parsing
Part names using European decimal notation (e.g. "4,7 kΩ", "2,2uF") were parsed incorrectly because the regex only recognized dots. Now commas are normalized to dots before parsing, matching the existing pattern used elsewhere in the codebase (PartNormalizer, price providers).
1 parent f75c5d7 commit 93b9b29

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

src/Doctrine/Functions/SiValueSort.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ public function getSql(SqlWalker $sqlWalker): string
8282
assert($this->field !== null, 'Field is not set');
8383

8484
$platform = $sqlWalker->getConnection()->getDatabasePlatform();
85-
$fieldSql = $this->field->dispatch($sqlWalker);
85+
$rawField = $this->field->dispatch($sqlWalker);
86+
87+
// Normalize comma decimal separator to dot for SQL platforms (European locale support)
88+
$fieldSql = "REPLACE({$rawField}, ',', '.')";
8689

8790
if ($platform instanceof PostgreSQLPlatform) {
8891
return $this->getPostgreSQLSql($fieldSql);
@@ -92,6 +95,9 @@ public function getSql(SqlWalker $sqlWalker): string
9295
return $this->getMySQLSql($fieldSql);
9396
}
9497

98+
// SQLite: comma normalization is handled in the PHP callback
99+
$fieldSql = $rawField;
100+
95101
if ($platform instanceof SQLitePlatform) {
96102
return "SI_VALUE({$fieldSql})";
97103
}
@@ -168,6 +174,9 @@ public static function sqliteSiValue(?string $value): ?float
168174
return null;
169175
}
170176

177+
// Normalize comma decimal separator to dot (European locale support)
178+
$value = str_replace(',', '.', $value);
179+
171180
// Match a number at the very start (allowing leading whitespace), optionally followed by an SI prefix
172181
if (!preg_match('/^\s*(\d+\.?\d*)\s*([pnuµmkKMGT])?/u', $value, $matches)) {
173182
return null;

tests/Doctrine/Functions/SiValueSortTest.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function testPostgreSQLGeneratesCaseExpression(): void
3737
$sql = $function->getSql($this->createSqlWalker(new PostgreSQLPlatform()));
3838

3939
$this->assertStringContainsString('CASE', $sql);
40-
$this->assertStringContainsString('substring(part_name', $sql);
40+
$this->assertStringContainsString("REPLACE(part_name, ',', '.')", $sql);
4141
$this->assertStringContainsString('1e-12', $sql);
4242
$this->assertStringContainsString('1e-9', $sql);
4343
$this->assertStringContainsString('1e-6', $sql);
@@ -56,7 +56,7 @@ public function testMySQLGeneratesCaseExpression(): void
5656
$sql = $function->getSql($this->createSqlWalker(new MySQLPlatform()));
5757

5858
$this->assertStringContainsString('CASE', $sql);
59-
$this->assertStringContainsString('REGEXP_SUBSTR(part_name', $sql);
59+
$this->assertStringContainsString("REPLACE(part_name, ',', '.')", $sql);
6060
$this->assertStringContainsString('1e-12', $sql);
6161
$this->assertStringContainsString('1e6', $sql);
6262
}
@@ -106,11 +106,16 @@ public static function sqliteSiValueProvider(): iterable
106106
yield 'plain_integer' => ['100', 100.0];
107107
yield 'plain_decimal' => ['4.7', 4.7];
108108

109-
// Decimal values with prefix
109+
// Decimal values with prefix (dot separator)
110110
yield 'decimal_nano' => ['4.7nF', 4.7e-9];
111111
yield 'decimal_micro' => ['0.1uF', 0.1e-6];
112112
yield 'decimal_kilo' => ['2.2k', 2.2e3];
113113

114+
// Comma decimal separator (European locale)
115+
yield 'comma_kilo' => ['4,7k', 4.7e3];
116+
yield 'comma_micro' => ['2,2uF', 2.2e-6];
117+
yield 'comma_kilo_space' => ['1,2 kΩ', 1.2e3];
118+
114119
// Number NOT at the start — should return NULL
115120
yield 'prefixed_name' => ['CAP-100nF', null];
116121
yield 'name_with_number' => ['R 4.7k 1%', null];

0 commit comments

Comments
 (0)