| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- """Split wave_file.point_name into device_part and device_point columns.
- Every rpm > 0 point_name has the shape ``{N号机组}{部位}{测点}``, e.g.
- ``7号机组二缸压力盖侧`` -> ``7号机组二缸`` + ``压力盖侧``. The split is a
- longest-known-suffix strip: the 测点 comes from a fixed whitelist of suffixes,
- the remainder must match ``\\d+号机组(?:[一二三四五六]缸|曲轴箱|电机)``, and
- reassembling must reproduce the original name. Any name failing these checks
- is reported and the write is aborted, so no data is ever lost or mangled.
- The mapping is computed locally from the distinct point_names, then written in
- a single ``UPDATE ... CASE point_name WHEN ... END`` (one pass over the table),
- covering every row whose point_name can be split (no rpm filter, so rpm<=0/NULL
- rows are backfilled too; already-correct rows are idempotently rewritten with
- the same values). ``device_point`` is added with an ``ALTER TABLE`` if it does
- not exist yet. Run without ``--commit`` to only preview the mappings.
- Usage:
- conda activate tspulse
- python split_device_point.py # preview only
- python split_device_point.py --commit # add column + write back
- """
- import argparse
- import re
- import sys
- from pathlib import Path
- BACKEND = Path(__file__).resolve().parents[1]
- sys.path.insert(0, str(BACKEND))
- from predict import get_connection # noqa: E402
- KNOWN_POINTS = [
- "压力盖侧",
- "压力轴侧",
- "活塞杆沉降",
- "十字头振动",
- "自由端振动",
- "驱动端振动",
- ]
- PART_RE = re.compile(r"^\d+号机组(?:[一二三四五六]缸|曲轴箱|电机)$")
- def split_name(name: str) -> tuple[str, str] | None:
- """Return (device_part, device_point) or None if the name does not fit."""
- for suffix in sorted(KNOWN_POINTS, key=len, reverse=True):
- if name.endswith(suffix):
- part = name[: -len(suffix)]
- if PART_RE.match(part):
- return part, suffix
- return None
- return None
- def build_mapping(connection) -> tuple[dict[str, tuple[str, str]], list[str]]:
- with connection.cursor() as cursor:
- cursor.execute("SELECT DISTINCT point_name FROM wave_file")
- names = [row["point_name"] for row in cursor.fetchall()]
- mapping: dict[str, tuple[str, str]] = {}
- failed: list[str] = []
- for name in names:
- split = split_name(name)
- if split is None:
- failed.append(name)
- else:
- mapping[name] = split
- return mapping, failed
- def main() -> int:
- parser = argparse.ArgumentParser(description="拆分 point_name 到 device_part/device_point")
- parser.add_argument("--commit", action="store_true",
- help="真正执行:新增 device_point 列并回写(默认仅预览)")
- args = parser.parse_args()
- with get_connection() as connection:
- mapping, failed = build_mapping(connection)
- if failed:
- print(f"以下 {len(failed)} 个 point_name 无法拆分,已中止,未做任何改动:")
- for name in failed:
- print(f" {name!r}")
- return 1
- print(f"共 {len(mapping)} 个 point_name,全部拆分成功:")
- for name, (part, point) in sorted(mapping.items()):
- print(f" {name:26} -> {part:12} | {point}")
- if not args.commit:
- print("\n未执行 --commit,仅预览。确认无误后加 --commit 回写。")
- return 0
- with connection.cursor() as cursor:
- cursor.execute(
- """
- SELECT COUNT(*) AS n FROM information_schema.columns
- WHERE table_schema = DATABASE()
- AND table_name = 'wave_file' AND column_name = 'device_point'
- """
- )
- if not cursor.fetchone()["n"]:
- cursor.execute(
- "ALTER TABLE wave_file ADD COLUMN device_point varchar(150) NOT NULL DEFAULT ''"
- )
- print("已新增列 device_point varchar(150) NOT NULL DEFAULT ''")
- names = sorted(mapping)
- placeholders = ",".join(["%s"] * len(names))
- case_part = " ".join(
- f"WHEN %s THEN %s" for _ in names
- )
- case_point = " ".join(f"WHEN %s THEN %s" for _ in names)
- sql = f"""
- UPDATE wave_file
- SET device_part = CASE point_name {case_part} END,
- device_point = CASE point_name {case_point} END
- WHERE point_name IN ({placeholders})
- """
- params: list[str] = []
- for name in names:
- params.extend([name, mapping[name][0]])
- for name in names:
- params.extend([name, mapping[name][1]])
- params.extend(names)
- with connection.cursor() as cursor:
- affected = cursor.execute(sql, tuple(params))
- print(f"已回写 {affected} 行(point_name 可拆的全部行)。")
- return 0
- if __name__ == "__main__":
- sys.exit(main())
|