修复业务镜像日期格式 (#59)
This commit is contained in:
parent
9c179f6170
commit
955ddb5e26
@ -106,7 +106,6 @@ class BusinessMirrorSynchronizer
|
||||
?Carbon $windowEnd,
|
||||
int $limit,
|
||||
): array {
|
||||
$names = array_map(fn (array $column): string => (string) $column['column_name'], $columns);
|
||||
$order = $this->orderColumns($dataset, $mode);
|
||||
$where = [];
|
||||
$bindings = [];
|
||||
@ -129,7 +128,7 @@ class BusinessMirrorSynchronizer
|
||||
}
|
||||
|
||||
$sql = 'SELECT TOP (' . $limit . ') '
|
||||
. implode(', ', array_map(fn (string $name): string => $this->quote($name), $names))
|
||||
. implode(', ', array_map(fn (array $column): string => $this->selectExpression($column), $columns))
|
||||
. ' FROM ' . $this->quote($dataset->sourceSchema()) . '.' . $this->quote($dataset->sourceObject())
|
||||
. ($where === [] ? '' : ' WHERE (' . implode(') AND (', $where) . ')')
|
||||
. ' ORDER BY ' . implode(', ', array_map(fn (string $name): string => $this->quote($name), $order));
|
||||
@ -137,6 +136,22 @@ class BusinessMirrorSynchronizer
|
||||
return $this->queries->forSource($dataset->sourceKey())->select($sql, $bindings);
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $column */
|
||||
private function selectExpression(array $column): string
|
||||
{
|
||||
$name = (string) $column['column_name'];
|
||||
$quoted = $this->quote($name);
|
||||
|
||||
// FreeTDS may return SQL Server date values using the connection locale
|
||||
// (for example "Jan 1 2026"). Convert temporal columns at the source so
|
||||
// every mirror receives deterministic ISO values that MariaDB accepts.
|
||||
return match (strtolower((string) ($column['data_type'] ?? ''))) {
|
||||
'date' => 'CONVERT(varchar(10), ' . $quoted . ', 23) AS ' . $quoted,
|
||||
'datetime', 'datetime2', 'smalldatetime' => 'CONVERT(varchar(27), ' . $quoted . ', 126) AS ' . $quoted,
|
||||
default => $quoted,
|
||||
};
|
||||
}
|
||||
|
||||
private function sqlServerDateTime(?Carbon $value): ?string
|
||||
{
|
||||
// ISO 8601 with millisecond precision is accepted consistently by SQL Server
|
||||
|
||||
@ -69,6 +69,7 @@ class BusinessMirrorSynchronizerTest extends TestCase
|
||||
$this->column('Id', 1, 'int', null),
|
||||
$this->column('updateTime', 2, 'datetime2', null),
|
||||
$this->column('displayName', 3, 'nvarchar', 120),
|
||||
$this->column('businessDate', 4, 'date', null),
|
||||
]);
|
||||
|
||||
$this->query = new FakeBusinessMirrorQuery();
|
||||
@ -88,8 +89,8 @@ class BusinessMirrorSynchronizerTest extends TestCase
|
||||
public function test_full_sync_materializes_complete_table_and_marks_state_ready(): void
|
||||
{
|
||||
$this->query->batches = [[
|
||||
['Id' => 1, 'updateTime' => '2026-08-14 10:00:00.1234567', 'displayName' => '一号'],
|
||||
['Id' => 2, 'updateTime' => '2026-08-14 11:00:00.0000000', 'displayName' => '二号'],
|
||||
['Id' => 1, 'updateTime' => '2026-08-14 10:00:00.1234567', 'displayName' => '一号', 'businessDate' => '2026-08-14'],
|
||||
['Id' => 2, 'updateTime' => '2026-08-14 11:00:00.0000000', 'displayName' => '二号', 'businessDate' => '2026-08-15'],
|
||||
]];
|
||||
|
||||
$result = $this->synchronizer->sync('test.dbo.records', true, 10, 1);
|
||||
@ -105,6 +106,8 @@ class BusinessMirrorSynchronizerTest extends TestCase
|
||||
$this->assertNotNull($state->initial_completed_at);
|
||||
$this->assertSame(2, (int) $state->mirror_row_count);
|
||||
$this->assertStringContainsString('SELECT TOP (10)', $this->query->calls[0]['sql']);
|
||||
$this->assertStringContainsString('CONVERT(varchar(27), [updateTime], 126) AS [updateTime]', $this->query->calls[0]['sql']);
|
||||
$this->assertStringContainsString('CONVERT(varchar(10), [businessDate], 23) AS [businessDate]', $this->query->calls[0]['sql']);
|
||||
$this->assertStringContainsString('ORDER BY [Id]', $this->query->calls[0]['sql']);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user