---

# Business Logic — JBSbatKKDelSavePrdKikData.createSqlS() [152 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.business.service.JBSbatKKDelSavePrdKikData` |
| Layer | Service (Batch-side service component) |
| Module | `service` (Package: `eo.business.service`) |

## 1. Role

### JBSbatKKDelSavePrdKikData.createSqlS()

This method generates a batch **physical deletion SQL statement** for deleting records from a target database table using a configurable WHERE clause with multi-column IN predicates. The method is a core component of a physical record deletion batch process (physical deletion = soft-delete-to-hard-delete, where records are marked as deleted and then actually removed). It constructs a `DELETE FROM ... WHERE col1 IN (...) AND col2 IN (...) ...` statement where the column names are dynamically provided via the `delSchemaInfo` parameter and the actual key values are collected across a range (`start` to `end`) of rows from the `delKeyInfo` parameter. Before returning the SQL, it delegates to `delRecOutput()` to export the records that will be deleted into a CSV file for audit and recovery purposes. The method implements a **builder pattern** for SQL construction, iterating over multiple key columns (up to 5) to build corresponding IN-clause value lists. It acts as a **shared SQL generator** called by the batch processing entry point `delSqlRunS`, and serves as the bridge between batch key-value collection and actual SQL execution downstream.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["createSqlS starts"])

    START --> LOG1["Log: Physical SQL creation"]
    LOG1 --> INIT["Initialize sqlBuff, whereBuff"]
    INIT --> CHECK_SIZE{"delKeyInfo.size() < loopEnd?"}
    CHECK_SIZE -->|Yes| ADJUST["loopEnd = delKeyInfo.size()"]
    CHECK_SIZE -->|No| BUILD_SQL["sqlBuff = DELETE FROM table"]
    ADJUST --> BUILD_SQL
    BUILD_SQL --> CREATE_LISTS["Create delKey1..delKey5 ArrayLists"]
    CREATE_LISTS --> LOOP_START["Loop j from start to loopEnd"]
    LOOP_START --> GET_DELINFO["delInf = delKeyInfo.get(j)"]
    GET_DELINFO --> ADD_KEYS["Add delInf[0..4] to delKey1..delKey5"]
    ADD_KEYS --> INC_J{"j < loopEnd?"}
    INC_J -->|Yes| LOOP_START
    INC_J -->|No| WHERE1["whereBuff: WHERE col1 IN (delKey1 values)"]
    WHERE1 --> CHECK_COL2{"delSchemaInfo[2] != null?"}
    CHECK_COL2 -->|Yes| COL2_IN["whereBuff: AND col2 IN (delKey2 values)"]
    CHECK_COL2 -->|No| CHECK_COL3
    COL2_IN --> CHECK_COL3{"delSchemaInfo[3] != null?"}
    CHECK_COL3 -->|Yes| COL3_IN["whereBuff: AND col3 IN (delKey3 values)"]
    CHECK_COL3 -->|No| CHECK_COL4
    COL3_IN --> CHECK_COL4{"delSchemaInfo[4] != null?"}
    CHECK_COL4 -->|Yes| COL4_IN["whereBuff: AND col4 IN (delKey4 values)"]
    CHECK_COL4 -->|No| CHECK_COL5
    COL4_IN --> CHECK_COL5{"delSchemaInfo[5] != null?"}
    CHECK_COL5 -->|Yes| COL5_IN["whereBuff: AND col5 IN (delKey5 values)"]
    CHECK_COL5 -->|No| APPEND_WHERE["sqlBuff.append(whereBuff)"]
    COL5_IN --> APPEND_WHERE
    APPEND_WHERE --> DELREC["Call delRecOutput(table, whereSql)"]
    DELREC --> LOG2["Log physical deletion SQL"]
    LOG2 --> RETURN["Return sqlBuff.toString()"]
    RETURN --> END(["createSqlS ends"])
```

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `delSchemaInfo` | `String[]` | Schema definition array describing the target table and its deletion key columns. Index `[0]` contains the target table name; `[1]` through `[5]` contain column names forming the WHERE clause (columns at `[2]`–`[5]` are optional — when `null`, that column is omitted from the WHERE clause, allowing variable-key-length deletion targets). |
| 2 | `delKeyInfo` | `ArrayList<String[]>` | List of key-value tuples, where each inner array `[0]`–`[4]` holds the key column values for one record to be deleted. The list is built by a preceding batch step that collects the records matching the deletion criteria. |
| 3 | `start` | `int` | Start index (inclusive) within `delKeyInfo` from which to collect key values. Enables chunked/batched processing so that large deletion sets can be split across multiple invocations. |
| 4 | `end` | `int` | End index (exclusive) within `delKeyInfo` for collecting key values. The method defensively caps this value if `delKeyInfo.size()` is less than `end` to prevent `IndexOutOfBoundsException`. |

**Instance fields read by this method:**

| Field | Type | Business Description |
|-------|------|---------------------|
| `super.logPrint` | Logger/Debug utility | Debug log output object inherited from the parent class, used to emit trace messages for the physical SQL creation and the final generated SQL. |

## 4. CRUD Operations / Called Services

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| - | `JBSbatKKDelSavePrdKikData.delRecOutput` | JBSbatKKDelSavePrdKikData | `<delSchemaInfo[0]>` (dynamic table name) | Calls `delRecOutput` to export deletion-target records to CSV before deletion. This internally executes a `SELECT * FROM <table> WHERE ...` and writes the result set to CSV. |
| - | `JBSbatDateUtil.getSystemDateTimeStamp` | (utility) | - | Returns the current system date/time stamp string (used in commented-out UPDATE SQL logic, not active in current code). |

**CRUD classification note:** The `createSqlS` method itself constructs a `DELETE` SQL statement but does **not** execute it — it returns the SQL string for the caller to execute. The `delRecOutput` call performs a `SELECT` (Read) against the target table for CSV export purposes before the actual deletion occurs.

## 5. Dependency Trace

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Batch: `JBSbatKKDelSavePrdKikData.delSqlRunS` | `delSqlRunS` -> `createSqlS(delSchemaInfo, delKeyInfo, start, end)` | `delRecOutput [R] <dynamic_table>`, `printDebugLog [-]` |

**Trace detail:** The only known caller is `delSqlRunS`, a private method within the same class that orchestrates the physical deletion batch workflow. It iterates over deletion schema/key lists and calls `createSqlS` to generate the DELETE SQL for each batch segment. The terminal operations from this method are:
- `printDebugLog` (multiple calls for trace logging)
- `delRecOutput` (SELECT + CSV export for the target table before deletion)

## 6. Per-Branch Detail Blocks

**Block 1** — [SET] `(initialization) (L6598)`

> Initializes the StringBuffer builders and logs the start of SQL creation.

| # | Type | Code |
|---|------|------|
| 1 | CALL | `super.logPrint.printDebugLog("*** Physical SQL creation ***")` // Japanese: 物理削除SQLの作成 — debug trace [JBSbatKKDelSavePrdKikData] |
| 2 | SET | `sqlBuff = new StringBuffer()` // Buffer for building the DELETE SQL string |
| 3 | SET | `whereBuff = new StringBuffer()` // Buffer for building the WHERE clause |

**Block 2** — [IF-ELSE-IF] `(loopEnd bounds check) (L6667)`

> Adjusts the loop end index to prevent out-of-bounds access when the key info list is shorter than expected. Japanese comment: 削除終了要素数が削除キーより多いとき削除終了要素数を削除キーの要素数に合わせる — "When the number of deletion-end elements is greater than the deletion key, align the deletion-end count to the deletion key element count."

| # | Type | Code |
|---|------|------|
| 1 | SET | `loopEnd = end` // Initialize loop boundary with input parameter |
| 2 | IF | `delKeyInfo.size() < loopEnd` — bounds safety check |
| 2.1 | SET | `loopEnd = delKeyInfo.size()` // Cap to actual list size |

**Block 3** — [SET] `(DELETE FROM prefix) (L6674)`

> Begins constructing the DELETE SQL statement.

| # | Type | Code |
|---|------|------|
| 1 | SET | `sqlBuff.append("DELETE FROM " + delSchemaInfo[0])` // Table name from index 0 of schema array |

**Block 4** — [SET] `(key ArrayList creation) (L6676)`

> Creates five separate ArrayLists, one for each potential key column, to collect key values across the batch range.

| # | Type | Code |
|---|------|------|
| 1 | SET | `delKey1 = new ArrayList<String>()` // Values for key column 1 |
| 2 | SET | `delKey2 = new ArrayList<String>()` // Values for key column 2 |
| 3 | SET | `delKey3 = new ArrayList<String>()` // Values for key column 3 |
| 4 | SET | `delKey4 = new ArrayList<String>()` // Values for key column 4 |
| 5 | SET | `delKey5 = new ArrayList<String>()` // Values for key column 5 |

**Block 5** — [FOR LOOP] `(collect key values from delKeyInfo) (L6682)`

> Iterates from `start` to `loopEnd`, extracting each row's key values into the corresponding delKey ArrayLists.

| # | Type | Code |
|---|------|------|
| 1 | SET | `delInf = delKeyInfo.get(j)` // Current key tuple |
| 2 | EXEC | `delKey1.add(delInf[0])` // Column 1 key value |
| 3 | EXEC | `delKey2.add(delInf[1])` // Column 2 key value |
| 4 | EXEC | `delKey3.add(delInf[2])` // Column 3 key value |
| 5 | EXEC | `delKey4.add(delInf[3])` // Column 4 key value |
| 6 | EXEC | `delKey5.add(delInf[4])` // Column 5 key value |

**Block 6** — [SET] `(WHERE clause - column 1) (L6690)`

> Builds the first WHERE condition: `WHERE col1 IN ('val1', 'val2', ...)`.

| # | Type | Code |
|---|------|------|
| 1 | SET | `whereBuff.append("WHERE " + delSchemaInfo[1] + " IN ('" + delKey1.get(start) + "'")` // First value |
| 2 | FOR LOOP | `i from start+1 to loopEnd` — append remaining values |
| 2.1 | SET | `whereBuff.append(" ,'", delKey1.get(i) + "'")` // Additional values |
| 3 | SET | `whereBuff.append(")")` // Close IN clause |

**Block 7** — [IF-ELSE-IF] `(WHERE clause - optional columns 2-5) (L6693–L6742)`

> For each optional key column (indices 2 through 5 of `delSchemaInfo`), if the column name is not `null`, appends an `AND colN IN (...)` predicate. Each follows the same pattern: first value, loop for remaining values, close parentheses.

**Block 7.1** — [IF] `(delSchemaInfo[2] != null) (L6693)`

> Japanese comment: WHERE句生成 条件項目2 — "WHERE clause generation condition item 2."

| # | Type | Code |
|---|------|------|
| 1 | SET | `whereBuff.append(" AND " + delSchemaInfo[2] + " IN ('" + delKey2.get(start) + "'")` |
| 2 | FOR LOOP | `i from start+1 to loopEnd` |
| 2.1 | SET | `whereBuff.append(" ,'", delKey2.get(i) + "'")` |
| 3 | SET | `whereBuff.append(")")` // ST-2015-0000017 MOD — properly closes IN clause per loop |

**Block 7.2** — [IF] `(delSchemaInfo[3] != null) (L6703)`

> Japanese comment: WHERE句生成 条件項目3 — "WHERE clause generation condition item 3."

| # | Type | Code |
|---|------|------|
| 1 | SET | `whereBuff.append(" AND " + delSchemaInfo[3] + " IN ('" + delKey3.get(start) + "'")` |
| 2 | FOR LOOP | `i from start+1 to loopEnd` |
| 2.1 | SET | `whereBuff.append(" ,'", delKey3.get(i) + "'")` |
| 3 | SET | `whereBuff.append(")")` // ST-2015-0000017 MOD |

**Block 7.3** — [IF] `(delSchemaInfo[4] != null) (L6713)`

> Japanese comment: WHERE句生成 条件項目4 — "WHERE clause generation condition item 4."

| # | Type | Code |
|---|------|------|
| 1 | SET | `whereBuff.append(" AND " + delSchemaInfo[4] + " IN ('" + delKey4.get(start) + "'")` |
| 2 | FOR LOOP | `i from start+1 to loopEnd` |
| 2.1 | SET | `whereBuff.append(" ,'", delKey4.get(i) + "'")` |
| 3 | SET | `whereBuff.append(")")` // ST-2015-0000017 MOD |

**Block 7.4** — [IF] `(delSchemaInfo[5] != null) (L6723)`

> Japanese comment: WHERE句生成 条件項目5 — "WHERE clause generation condition item 5."

| # | Type | Code |
|---|------|------|
| 1 | SET | `whereBuff.append(" AND " + delSchemaInfo[5] + " IN ('" + delKey5.get(start) + "'")` |
| 2 | FOR LOOP | `i from start+1 to loopEnd` |
| 2.1 | SET | `whereBuff.append(" ,'", delKey5.get(i) + "'")` |
| 3 | SET | `whereBuff.append(")")` // ST-2015-0000017 MOD |

**Block 8** — [CALL] `(append WHERE clause and export records) (L6736)`

> Finalizes the SQL by appending the WHERE clause, then calls `delRecOutput` to CSV-export the records that will be deleted.

| # | Type | Code |
|---|------|------|
| 1 | SET | `sqlBuff.append(whereBuff)` // Append complete WHERE clause |
| 2 | CALL | `delRecOutput(delSchemaInfo[0], whereBuff.toString())` // Export deletion-target records to CSV for audit/recovery |

**Block 9** — [EXEC] `(debug logging) (L6739)`

> Japanese comment: デバッグロぐ出力 — "Debug log output."

| # | Type | Code |
|---|------|------|
| 1 | CALL | `super.logPrint.printDebugLog("【Physical deletion SQL】" + sqlBuff.toString())` // Log the final DELETE SQL |

**Block 10** — [RETURN] `(return SQL string) (L6741)`

| # | Type | Code |
|---|------|------|
| 1 | RETURN | `return sqlBuff.toString()` // The complete DELETE SQL statement for the caller to execute |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `delSchemaInfo[0]` | Field | Target table name — the database table from which records will be physically deleted |
| `delSchemaInfo[1..5]` | Field | Key column names — database column names used in the WHERE clause to identify records for deletion. Columns 2–5 are optional (nullable) |
| `delKeyInfo` | Field | Deletion key information — a list of key-value tuples where each row represents the composite key of one record to be deleted |
| `delKey1..delKey5` | Variable | Temporary ArrayLists collecting individual column values across all records in the deletion batch range |
| physical deletion | Business term | 物理削除 (Butsuri Sakujyo) — The actual removal of records from a database table, as opposed to soft deletion which merely marks records as inactive. This batch process ensures records are properly exported to CSV before being permanently deleted. |
| SQL | Technical term | Structured Query Language — the standard language for relational database operations |
| IN clause | Technical term | SQL WHERE clause predicate `column IN ('val1', 'val2', ...)` that matches any of a list of values, used here for batch matching of multiple records |
| CSV | Technical term | Comma-Separated Values — file format used to export deletion-target records for audit trail and recovery purposes |
| delRecOutput | Method | Record export method — queries the database for records matching the WHERE clause and writes them to a CSV file for audit/compliance before deletion |
| batchUserId | Field | Batch user ID — the system user identifier performing the deletion operation (inherited from parent class) |
| opeDate | Field | Operation date — the business date of the deletion operation (inherited from parent class) |
| jobid | Field | Job ID — the batch job identifier (inherited from parent class) |
| ST-2015-0000017 | Change ticket | A change/modification ticket that fixed the WHERE clause IN-clause closing parenthesis handling — ensuring each optional column's IN clause is properly closed with a `)` after the loop |

---