CaiWuXiTong/app/Console/Commands/InspectUpstream.php

67 lines
3.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Modules\EcommerceFinance\Services\UpstreamReadOnlyQueryFactory;
use Modules\EcommerceFinance\Services\UpstreamSourceRegistry;
use Modules\EcommerceFinance\Services\UpstreamSqlDialect;
use Throwable;
class InspectUpstream extends Command
{
protected $signature = 'upstream:inspect {source?} {schema?} {object?} {--columns= : 明确选择样本字段;不填时只显示字段目录} {--limit=5 : 样本上限,最多20行}';
protected $description = '通过统一驱动查看目录或有限只读样本,不生成快照或启动同步';
public function handle(UpstreamSourceRegistry $sources, UpstreamReadOnlyQueryFactory $queries): int
{
$source = (string) $this->argument('source');
$schema = (string) $this->argument('schema');
$object = (string) $this->argument('object');
try {
if ($source === '') {
$rows = [];
foreach ($sources->all() as $key => $definition) $rows[] = [$key, $definition['label'], $sources->driver($key), $sources->enabled($key) ? '启用' : '停用'];
$this->table(['内部标识', '数据库名称', '类型', '状态'], $rows);
return self::SUCCESS;
}
$sources->definition($source);
if ($schema === '' || $object === '') {
$objects = DB::table('upstream_schema_columns')->where('source_key', $source)
->when($schema !== '', fn ($q) => $q->where('schema_name', $schema))
->select('schema_name', 'object_name')->distinct()->orderBy('schema_name')->orderBy('object_name')->get();
$this->table(['Schema', '表 / 视图'], $objects->map(fn ($row) => [$row->schema_name, $row->object_name])->all());
return self::SUCCESS;
}
$catalog = DB::table('upstream_schema_columns')->where('source_key', $source)
->where('schema_name', $schema)->where('object_name', $object)->orderBy('ordinal_position')
->get(['column_name', 'data_type', 'is_nullable']);
if ($catalog->isEmpty()) {
$this->error('尚无该对象的字段目录,请先核实来源并同步数据字典。');
return self::FAILURE;
}
if (! $this->option('columns')) {
$this->table(['字段', '类型', '允许空值'], $catalog->map(fn ($c) => [$c->column_name, $c->data_type, $c->is_nullable ? '是' : '否'])->all());
return self::SUCCESS;
}
$columns = array_values(array_unique(array_filter(array_map('trim', explode(',', (string) $this->option('columns'))))));
if ($columns === [] || array_diff($columns, $catalog->pluck('column_name')->all())) {
$this->error('样本字段必须来自该对象的数据字典。');
return self::FAILURE;
}
$dialect = new UpstreamSqlDialect($sources->driver($source));
$sql = $dialect->select(implode(', ', array_map($dialect->quote(...), $columns)),
'FROM ' . $dialect->quote($schema) . '.' . $dialect->quote($object),
min(max((int) $this->option('limit'), 1), 20));
$rows = $queries->forSource($source)->select($sql);
$this->table($columns, array_map(fn ($row) => array_values($row), $rows));
$this->info('样本仅用于字段核实,不能作为完整业务数据。');
return self::SUCCESS;
} catch (Throwable) {
$this->error('只读检查未完成,请检查共享连接、来源启用状态和访问权限。');
return self::FAILURE;
}
}
}