Newer
Older
client_dwatch / docs / handoff / analysis / ddl-diff-dbpull.md

【注記】 2026-09-03、TeamWorks 提供の実DDL(clean_watch_20260902.sql)と手書き prisma/schema.prisma の答え合わせのために作成した記録です(prisma db pull による方法)。 同じ照合を別方法(DDL文の直接パース)で行った ddl-diff-parse.md と対になる相互検証の記録です。 当時の記録であり、現行方針ではありません。 以降の決定は docs/decisions.md と docs/handoff.md を参照してください。

30 — 実DDL と 手書き schema.prisma の答え合わせ(prisma db pull)

  • 実施日: 2026-09-03
  • 入力DDL: C:\Users\daich\Downloads\clean_watch_20260902.sql(46,390 bytes / CREATE TABLE 39個)
    • MySQL dump 10.13, Distrib 8.0.41 (Linux x86_64) / 元DB名 clean_watch
  • 手書き版: C:\Users\daich\dev\d-watch\prisma\schema.prisma(28モデル / md5 a1d48b7927c2b93171d3394986abbdf1)
  • 生成版: <scratchpad>\ddl\pulled.prisma(39モデル / 703行)
  • 比較スクリプト: <scratchpad>\ddl\compare.py → 生出力 diff.txt / 構造化 diff.json

0. 作業条件(守った制約)

制約 実施内容 確認
prisma/schema.prisma を上書きしない db pull --print で標準出力へ出し、--schema にはscratchpadのスタブを指定 実行後 md5 変化なし / git status 空
ローカルDB dwatch_local を壊さない DDL は新規 dwatch_ddl へ投入 dwatch_local のテーブル数 28 のまま
.env.local を書き換えない --url フラグで接続先を一時的に上書き ファイル無変更
リポジトリへ書き込まない 作業ファイルはすべて scratchpad 配下 git status 空
手書き版を修正しない 差分抽出のみ。修正は行っていない —

Laravel 基盤10テーブルは比較対象外として除外した: users / sessions / jobs / migrations / cache / cache_locks / failed_jobs / job_batches / password_reset_tokens / personal_access_tokens → 業務テーブルは DDL 側 29個、手書き側 28モデル。


1. DDL 読み込みの結果

成功。エラー・警告は0件。

1-1. 事前確認した内容

確認項目 結果
文字コード /*!50503 SET NAMES utf8mb4 */。各テーブル DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
CREATE DATABASE 文 無し
USE 文 無し(→ 意図しないDBに入る危険は無いが、投入先をコマンドラインで明示する必要がある)
SET 文 TIME_ZONE='+00:00' / SQL_MODE='NO_AUTO_VALUE_ON_ZERO' / SQL_NOTES=0
外部キーチェック無効化 あり(FOREIGN_KEY_CHECKS=0, UNIQUE_CHECKS=0)。バージョンガード付きコメント形式
INSERT / VIEW / TRIGGER / PROCEDURE 無し(純粋なスキーマのみ。データは含まれない)
DROP TABLE IF EXISTS 各テーブルの前に有り

USE 文が無いため、投入先DBは接続時に明示した。

1-2. 実行コマンドと結果

mysql -u root -e "CREATE DATABASE dwatch_ddl CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -u root --default-character-set=utf8mb4 dwatch_ddl < clean_watch_20260902.sql
  • 終了コード 0 / 標準エラー出力なし
  • information_schema 上のテーブル数: dwatch_ddl = 39(DDLの CREATE TABLE 数と一致)
  • dwatch_local = 28(投入前後で不変)
  • サーバは MySQL 8.4.9、dump 元は 8.0.41。バージョン差による失敗は発生しなかった。

1-3. db pull

Prisma 7 では datasource ブロックに url を書けない(P1012)。 最初にスタブへ url = env(...) を書いて1度失敗したため、url を削って --url フラグで渡す形に変更し成功した。 この失敗はスタブ側の書き方の問題で、DDL/DBには影響していない。

npx prisma db pull --print \
  --schema="<scratchpad>/ddl/stub.prisma" \
  --url="mysql://root@localhost:3306/dwatch_ddl"

終了コード 0。生成結果 39モデル。


2. テーブル単位の差分

差分 1件。

種別 テーブル 内容
手書きに無い clean_link_schedules 定義書に存在しなかった新テーブル。手書き版に未実装
生成版に無い (無し) 手書き版の28モデルはすべて実DDLに存在した

業務テーブル 29 のうち 28 は名前レベルで一致。@@map の物理名も全件一致した。

2-1. clean_link_schedules の全カラム(新テーブル)

link_schedules と構造が完全に同一(カラム名・型・既定値・NULL許容・FK先すべて)。 唯一の違いは制約名の接頭辞(clean_link_schedules_section_id_foreign)と、link_schedules 側に AUTO_INCREMENT=10 が入っている点(データ有無の差)。

# カラム DDL型 NULL 既定値 Prisma
1 id bigint unsigned AUTO_INCREMENT NOT NULL — BigInt @id @default(autoincrement()) @db.UnsignedBigInt
2 section_id bigint unsigned NOT NULL — BigInt @db.UnsignedBigInt
3 type tinyint unsigned NOT NULL 1 Int @default(1) @db.UnsignedTinyInt
4 weeks varchar(7) NOT NULL — String @db.VarChar(7)
5 intervals varchar(120) NOT NULL — String @db.VarChar(120)
6 inactive tinyint unsigned NOT NULL 0 Int @default(0) @db.UnsignedTinyInt
7 created_at timestamp NOT NULL CURRENT_TIMESTAMP DateTime @default(now()) @db.Timestamp(0)
8 updated_at timestamp NOT NULL CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP DateTime @default(now()) @db.Timestamp(0)(@updatedAt 相当)
9 deleted_at timestamp NULL NULL DateTime? @db.Timestamp(0)
  • 主キー: PRIMARY KEY (id)
  • インデックス: KEY clean_link_schedules_section_id_foreign (section_id)
  • 外部キー: section_id → sections(id)(ON DELETE / ON UPDATE 指定なし = NoAction)
  • ユニーク制約: なし

link_schedules と clean_link_schedules が両方存在し中身が同一という点は、どちらを参照すべきか TeamWorks に要確認(旧テーブルの残置か、用途別の並存か判断できない)。


3. カラム単位の差分(テーブルごと)

カラムの有無の差分は 14件(生成版にあって手書きに無い 3 / 手書きにあって実DDLに無い 11)。 うち 3件はカラム名の綴り違い(リネーム)で、実質は「6件のリネーム片側」+「8件の実在しないカラム」。

業務カラム総数: 手書き 311 / 生成版 312。

3-1. 生成版にあって手書き版に無いカラム(3件)

テーブル カラム 型 NULL 備考
robot_error_reports responded_at DateTime? @db.DateTime(0) 可 手書きは responsed_at(下記リネーム)
control_error_histories responded_at DateTime? @db.DateTime(0) 可 手書きは responsed_at(下記リネーム)
control_reports serial_number String @db.VarChar(100) 不可 手書きは sireal_number(下記リネーム)

3-2. 手書き版にあって実DDLに無いカラム(11件)

テーブル カラム 手書きの型 判定
robot_error_reports responsed_at DateTime? @db.DateTime(0) リネーム → responded_at
control_error_histories responsed_at DateTime? @db.DateTime(0) リネーム → responded_at
control_reports sireal_number String @db.VarChar(100) リネーム → serial_number
clean_schedules started_at DateTime? @db.DateTime(0) 実DDLに存在しない
clean_schedules ended_at DateTime? @db.DateTime(0) 実DDLに存在しない
clean_statuses deleted_at DateTime? @db.Timestamp(0) 実DDLに存在しない(論理削除なし)
clean_timetable_histories inactive Int @default(0) @db.UnsignedTinyInt 実DDLに存在しない
robots task_id String? @db.VarChar(20) 実DDLに存在しない(robot_task_versions 側にある)
robots version String? @db.VarChar(20) 実DDLに存在しない(robot_task_versions 側にある)
section_robot_statuses indicatived_at DateTime? @db.Timestamp(0) 実DDLに存在しない
section_robot_statuses deleted_at DateTime? @db.Timestamp(0) 実DDLに存在しない

3-3. カラム名リネーム3件の DDL 原文(裏取り)

-- robot_error_reports
`responded_at` datetime DEFAULT NULL,
-- control_error_histories
`responded_at` datetime DEFAULT NULL,
-- control_reports
`serial_number` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,

responsed_at は定義書の typo であり、実カラム名は responded_at(d が入る)で確定。 control_reports.sireal_number も定義書の typo で、実カラム名は serial_number。


4. 型・既定値・null許容の差分

4-1. 型(Prisma型)の差分 — 1件

テーブル.カラム 手書き 生成版 DDL原文
customer_contacts.contact_type Int @db.UnsignedTinyInt BigInt @db.UnsignedBigInt bigint unsigned NOT NULL

同名カラムなのに facility_contacts.contact_type は tinyint unsigned(Int @db.UnsignedTinyInt)で、 実DDL上で顧客側と施設側の型が食い違っている。手書き版は両方 tinyint に揃えていたため顧客側が外れた。

4-2. @db.* 属性(桁数・符号)の差分 — 4件

テーブル.カラム 手書き 生成版 DDL原文
customer_contacts.contact_type UnsignedTinyInt UnsignedBigInt bigint unsigned
facility_contacts.email VarChar(100) VarChar(255) varchar(255)
robot_error_reports.serial_number VarChar(50) VarChar(20) varchar(20)
robot_error_reports.product_code VarChar(50) VarChar(20) varchar(20)

customer_contacts.email は varchar(100) のまま(一致)。facility_contacts.email のみ 255。

4-3. NULL 許容の差分 — 1件

テーブル.カラム 手書き 生成版 DDL原文
robot_error_reports.errored_at DateTime(必須) DateTime?(NULL可) datetime DEFAULT NULL

同テーブルの responded_at / resolved_at / product_code などはいずれも手書きも NULL 可で一致。

4-4. 既定値の差分 — 15件

(a) 実装に影響する既定値差分(9件)

テーブル.カラム 手書き 生成版 DDL原文
clean_timetables.precheck @default(9) @default(0) tinyint unsigned NOT NULL DEFAULT '0'
clean_timetables.parent_id @default(0) 既定値なし bigint unsigned NOT NULL(DEFAULT句なし)
robots.battery @default(100) @default(0) tinyint unsigned NOT NULL DEFAULT '0'
robots.device_id @default(0) 既定値なし bigint unsigned NOT NULL(DEFAULT句なし)
clean_task_reports.created_at @default(now()) 既定値なし timestamp NOT NULL(DEFAULT句なし)
clean_task_reports.updated_at @default(now()) 既定値なし timestamp NOT NULL(DEFAULT句なし)
security_status_histories.reported_at @default(now()) 既定値なし timestamp NOT NULL(DEFAULT句なし)
clean_status_histories.id @default(autoincrement()) 既定値なし bigint unsigned NOT NULL(AUTO_INCREMENT なし)
clean_timetable_histories.id @default(autoincrement()) 既定値なし bigint unsigned NOT NULL(AUTO_INCREMENT なし)

履歴系2テーブルの id は AUTO_INCREMENT ではない(採番はアプリ側 or 元テーブルの id を引き継ぐ設計)。 clean_task_reports の created_at / updated_at と security_status_histories.reported_at は DEFAULT句が無い timestamp NOT NULL なので、INSERT 時に明示的に値を入れる必要がある。

(b) 数値リテラル表記のみの差分(6件・値は同一)

テーブル.カラム 手書き 生成版
clean_statuses.task_area @default(0) @default(0.000000)
clean_statuses.clean_area @default(0) @default(0.000000)
clean_status_histories.task_area @default(0) @default(0.000000)
clean_status_histories.clean_area @default(0) @default(0.000000)
clean_task_reports.task_area @default(0) @default(0.000000)
clean_task_reports.clean_area @default(0) @default(0.000000)

DDL は decimal(12,6) unsigned NOT NULL DEFAULT '0.000000'。 数値としては同一だがリテラル表記が異なるため差分として計上した。生成版の表記に合わせるのが正。

4-5. 主キー / ユニークの差分 — 4件

テーブル.カラム 手書き 生成版 DDL原文
robot_error_reports.id @id @id なし PRIMARY KEY が存在しない
robot_error_reports.error_id 制約なし @unique UNIQUE KEY robot_error_reports_report_id_unique (error_id)
clean_status_histories.id @id @unique PRIMARY KEY なし / UNIQUE KEY clean_status_histories_id_unique (id)
clean_timetable_histories.id @id(+autoincrement) @id(autoincrement なし) PRIMARY KEY (id) のみ

robot_error_reports には PRIMARY KEY が一つも無い。 Prisma はモデルの一意識別子として error_id @unique を採用しており、 id(varchar(50))はただのカラムになっている。 つまり Prisma Client からは findUnique({ where: { id } }) が使えず、error_id でしか一意引きできない。

clean_status_histories も PRIMARY KEY が無く、id は UNIQUE KEY のみ。 手書き版のコメント「定義書原文のまま: キー種別が他テーブルの pk ではなく uk(unique key)と記載されている」は 実DDLと合っていた(定義書の記述は正しかった)が、Prisma 属性は @id ではなく @unique が正。

4-6. @updatedAt(Prisma固有・introspectionでは生成されない)

db pull は @updatedAt を出力しないため §4-4 の機械比較には出てこないが、 DDL の ON UPDATE CURRENT_TIMESTAMP の有無で検証すると以下の不整合がある。

テーブル.カラム 手書き DDL の ON UPDATE CURRENT_TIMESTAMP 判定
clean_task_reports.updated_at @updatedAt 無し(DEFAULT句すら無い) 誤り
facility_contacts.updated_at @updatedAt 無し(DEFAULT CURRENT_TIMESTAMP のみ) 誤り
section_robot_statuses.updated_at @updatedAt 無し(DEFAULT CURRENT_TIMESTAMP のみ) 誤り
security_statuses.reported_at 指定なし 有り 付け漏れ
上記以外の updated_at 18件 @updatedAt 有り 一致

5. リレーション(外部キー)の差分

差分 3件。すべて「手書き版が実在しない外部キーを張っていた」方向。 生成版にあって手書きに無い外部キーは 0件(新テーブル clean_link_schedules の1本を除く)。

テーブル 手書きが張っていたFK 実DDL
clean_statuses clean_timetable_id → clean_timetables(id) FK なし(clean_timetable_id bigint unsigned NOT NULL だがインデックスも無い)
clean_status_histories clean_timetable_id → clean_timetables(id) FK なし(同上)
robot_task_versions clean_schedule_id → clean_schedules(id) FK なし(KEY も無い。FKは robot_id → robots(id) の1本だけ)

5-1. 特に確認を依頼された項目の結果

確認項目 結果
devices.maker_id の型 tinyint unsigned NOT NULL(DEFAULT句なし)= Int @db.UnsignedTinyInt。手書き版と一致
makers への外部キー 存在しない。makers テーブル自体がDDLに含まれていない。devices の制約は PRIMARY KEY (id) のみ。TeamWorks回答(A-1)どおりで、手書き版の判断は正しかった
controls.facility_id の外部キー 存在する: CONSTRAINT controls_facility_id_foreign FOREIGN KEY (facility_id) REFERENCES facilities (id)。section_id → sections(id) も存在。手書き版と一致

5-2. 業務テーブルの外部キー一覧(実DDL・全件)

すべて ON DELETE / ON UPDATE 指定なし → Prisma は onDelete: NoAction, onUpdate: NoAction を生成。

テーブル 外部キー
customers group_id → groups(id)
facilities customer_id → customers(id)
sections facility_id → facilities(id)
controls facility_id → facilities(id), section_id → sections(id)
robots facility_id, section_id, device_id → devices(id)
robot_task_versions robot_id → robots(id) のみ
robot_instruct_histories robot_id → robots(id)
robot_error_reports facility_id, section_id, robot_id
section_robot_statuses facility_id, section_id
control_reports facility_id, section_id, control_id → controls(id)
control_error_histories facility_id, section_id, control_id
security_statuses facility_id, section_id
security_status_histories facility_id, section_id
clean_statuses facility_id, section_id(clean_timetable_id は無し)
clean_status_histories facility_id, section_id(clean_timetable_id は無し)
clean_task_reports facility_id, section_id, robot_id(clean_timetable_id は無し)
clean_schedules facility_id, section_id
clean_timetables facility_id, section_id, clean_schedule_id → clean_schedules(id)
clean_timetable_histories facility_id, section_id, clean_schedule_id
link_schedules section_id → sections(id)
clean_link_schedules section_id → sections(id)
customer_summaries / customer_error_summaries / customer_contacts customer_id → customers(id)
facility_summaries / facility_error_summaries / facility_contacts facility_id → facilities(id)
devices / groups なし

5-3. インデックスの差分 — 6件

テーブル 差分 方向
clean_timetable_histories [clean_schedule_id] / [start_at] / [end_at] 生成版のみ(手書きに欠落)
control_reports [control_id] 生成版のみ(手書きに欠落)
link_schedules [section_id] 生成版のみ(手書きに欠落)
robot_task_versions [clean_schedule_id] 手書きのみ(実DDLに無い)

補足: clean_timetable_histories のインデックス名は ..._started_at_index / ..._ended_at_index だが 対象カラムは start_at / end_at(DDL側の命名が実カラム名とずれている)。


6. 手書き版が正しかった点

業務テーブル28のうち、比較項目すべてが完全一致したのは 12 テーブル。

# テーブル カラム数
1 groups 6
2 devices 8
3 customers 13
4 facilities 18
5 sections 9
6 controls 12
7 robot_instruct_histories 4
8 security_statuses 7
9 customer_summaries 16
10 facility_summaries 16
11 customer_error_summaries 10
12 facility_error_summaries 10

(カラムの有無・Prisma型・@db.*・NULL許容・既定値・主キー・ユニーク・インデックス・外部キーのすべてが一致。 @updatedAt のみ introspection では検証不能なため §4-6 で別途確認済み。security_statuses.reported_at の付け漏れ1件を除き整合。)

6-1. 判断に迷った箇所が正解だった例

箇所 手書き版の判断 実DDL 判定
clean_statuses.clean_status Int @db.TinyInt(符号あり tinyint。A-2の回答で -1 があるため) tinyint NOT NULL DEFAULT '0'(unsigned なし) 正解
clean_status_histories.clean_status Int @db.TinyInt(符号あり) tinyint NOT NULL DEFAULT '0' 正解
customers.prefecture_cd Int @db.TinyInt(符号あり。facilities 側とは型が違うと明記) tinyint NOT NULL 正解
facilities.prefecture_cd Int @db.UnsignedTinyInt(符号なし) tinyint unsigned NOT NULL 正解(両テーブルの型差も正しく再現)
devices.maker_id Int @db.UnsignedTinyInt / makers へのFKは張らない tinyint unsigned NOT NULL / FKなし・makersテーブル自体なし 正解
facilities.shop_id String @default("0") @db.VarChar(20)(varchar なので文字列 "0" と判断) varchar(20) NOT NULL DEFAULT '0' 正解
facilities.contract String @default("0000000000") @db.VarChar(10) varchar(10) NOT NULL DEFAULT '0000000000' 正解
clean_schedules.start_time / end_time String @db.VarChar(4) varchar(4) NOT NULL 正解(時刻を4桁文字列で持つ設計)
clean_task_reports の主キー report_id String @id @db.VarChar(20) PRIMARY KEY (report_id) 正解(id ではなく report_id が PK)
robots.status Int @db.SmallInt(符号あり smallint) smallint NOT NULL DEFAULT '0' 正解
section_robot_statuses.robot_status Int @db.SmallInt smallint NOT NULL DEFAULT '0' 正解
customer_error_summaries.error_type String @db.VarChar(100) varchar(100) NOT NULL 正解
facility_error_summaries.error_type String @db.VarChar(100) varchar(100) NOT NULL 正解
customer_summaries / facility_summaries の面積 Decimal @db.Decimal(14, 6)(12,6 ではなく 14,6) decimal(14,6) unsigned NOT NULL 正解
同 比率カラム4種 operation_ratio / launch_ratio / clean_ratio / error_ratio すべて Int @db.UnsignedTinyInt・既定値なし tinyint unsigned NOT NULL(DEFAULT句なし) 正解(整数パーセント。小数は持たない)
control_error_histories.occurred_at DateTime @default(now()) @db.DateTime(0) datetime NOT NULL DEFAULT CURRENT_TIMESTAMP 正解(timestamp ではなく datetime に DEFAULT)
robot_error_reports.error_detail / comment String @db.Text / String? @db.Text text NOT NULL / text(NULL可) 正解
命名規約 フィールド名=物理カラム名(snake_case)、@@map で物理テーブル名 — 正解。db pull 出力との差分比較が単純な突き合わせで済んだ
clean_status_histories.id のキー種別 「pk ではなく uk と定義書に記載」とコメントで留保 PRIMARY KEY なし / UNIQUE KEY のみ 定義書の記述は正しかった(Prisma属性の選択のみ要修正)

makers テーブル、controls の facility FK、clean_schedules.end_time の型、 サマリの比率・面積の型と精度、error_type の型は、すべて手書き版が実DDLと一致していた。


7. 実装に影響する差分の優先順位

P1 — 直さないと動かない / データが取れない(8件)

# 差分 影響
1 robot_error_reports.responsed_at → responded_at 存在しないカラム参照。エラー詳細画面・対応日時の取得が全滅
2 control_error_histories.responsed_at → responded_at 同上(制御機エラー履歴)
3 control_reports.sireal_number → serial_number 存在しないカラム参照
4 robot_error_reports に PRIMARY KEY が無い → id の @id を外し error_id @unique を一意識別子にする @id を付けたままだと Prisma のスキーマ検証自体は通るが、実DBと不一致。findUnique({id}) は使えない。API の主キー設計を error_id 基準に見直す必要がある
5 clean_status_histories.id は @id ではなく @unique(PRIMARY KEY 無し) 同上。履歴の一意引きの前提が変わる
6 customer_contacts.contact_type が BigInt @db.UnsignedBigInt(facility 側は tinyint) Int と BigInt で TypeScript の型が変わる(number vs bigint)。両contactを共通の型で扱うコードは破綻する
7 手書きが張っていた実在しない外部キー 3本(clean_statuses.clean_timetable_id, clean_status_histories.clean_timetable_id, robot_task_versions.clean_schedule_id) include / select でリレーション取得を書くと実DBにFKが無いため設計前提が崩れる。JOIN は手書きで行う必要がある
8 clean_link_schedules が未実装 新テーブル。参照要否を TeamWorks に確認のうえモデル追加

P2 — 実行時エラーやデータ欠損につながる(7件)

# 差分 影響
9 robot_error_reports.errored_at が NULL 可 必須前提のコードで null 参照。発生日時が無いレコードを表示側で扱う必要がある
10 robot_error_reports.serial_number VarChar(50) → VarChar(20) 21文字以上の書き込みで切り詰め/エラー
11 robot_error_reports.product_code VarChar(50) → VarChar(20) 同上
12 clean_task_reports.created_at / updated_at が DEFAULT句なしの timestamp NOT NULL INSERT時に必ず値を入れる必要がある。@default(now()) 前提の書き込みは失敗する
13 security_status_histories.reported_at が DEFAULT句なし 同上
14 clean_status_histories.id / clean_timetable_histories.id が AUTO_INCREMENT でない 履歴INSERT時に id を自前で決める必要がある
15 @updatedAt の不整合3件(clean_task_reports / facility_contacts / section_robot_statuses)+ 付け漏れ1件(security_statuses.reported_at) DBが自動更新しないカラムを自動更新扱いにしている(逆も1件)。更新時刻がずれる

P3 — 表示・既定値の意味が変わる(6件)

# 差分 影響
16 clean_timetables.precheck 既定値 9 → 0 事前チェック状態の初期値解釈が変わる。9 の意味(未設定?)は定義書由来なので TeamWorks 要確認
17 robots.battery 既定値 100 → 0 新規ロボットのバッテリー初期表示が 0% になる
18 clean_timetables.parent_id / robots.device_id の 既定値 0 が実DDLに無い INSERT時に明示指定が必要
19 facility_contacts.email VarChar(100) → VarChar(255) 入力バリデーションの上限を緩める(customer 側は 100 のまま)
20 手書きにある実在しないカラム 8件(clean_schedules.started_at/ended_at, clean_statuses.deleted_at, clean_timetable_histories.inactive, robots.task_id/version, section_robot_statuses.indicatived_at/deleted_at) 参照するとエラー。特に clean_statuses / section_robot_statuses は 論理削除カラムが無いので deleted_at IS NULL 条件は書けない。robots.task_id/version は robot_task_versions から取る
21 インデックス差分 6件 機能には影響しないが @@index を実DDLに合わせる(robot_task_versions.clean_schedule_id は実DDLにインデックスも無いため、この列での検索はフルスキャンになる点に注意)

P4 — 表記のみ(2件)

# 差分 影響
22 Decimal 既定値のリテラル 0 → 0.000000(6箇所) 値は同一。生成版の表記に合わせる
23 link_schedules と clean_link_schedules の構造が完全同一 どちらを使うか TeamWorks 要確認(機能影響は参照先の選択次第)

8. 差分の総件数

区分 件数 内訳
テーブル 1 手書きに無い 1(clean_link_schedules)/生成版に無い 0
カラム(有無) 14 生成版のみ 3 / 手書きのみ 11(うち 3 はリネーム片側)
型(Prisma型) 1 customer_contacts.contact_type
@db.* 属性 4 contact_type / facility_contacts.email / serial_number / product_code
NULL 許容 1 robot_error_reports.errored_at
既定値 15 実質差分 9 + リテラル表記のみ 6
主キー 2 robot_error_reports.id / clean_status_histories.id
ユニーク 2 robot_error_reports.error_id / clean_status_histories.id
インデックス 6 生成版のみ 5 / 手書きのみ 1
リレーション(FK) 3 すべて手書きのみ(実在しないFK)
(参考)@updatedAt 4 誤り 3 / 付け漏れ 1。introspection では検証不能なため DDL の ON UPDATE で確認
  • 完全一致したテーブル: 12 / 28
  • 手書き版の物理名(@@map)は 28/28 すべて一致

9. 生成物

ファイル 内容
pulled.prisma db pull 生成物(703行 / 39モデル)。正とすべきスキーマ
pulled.raw 生成物の生出力(dotenv のログ2行を含む)
schema.prisma.HANDWRITTEN.bak 比較時点の手書き版のコピー(md5 a1d48b7927c2b93171d3394986abbdf1)
stub.prisma db pull に渡した最小スキーマ(generator + datasource のみ)
compare.py モデル単位・フィールド単位の機械比較スクリプト
diff.txt 比較の生出力
diff.json 比較結果の構造化データ
pull.stderr.log db pull の標準エラー出力

投入先DB dwatch_ddl は残してある(不要になれば DROP DATABASE dwatch_ddl;)。 dwatch_local は一切変更していない。

手書き版 prisma/schema.prisma は未修正。修正は別指示で行う。