# 機能設計書 174-Invoke-DbaQuery

## 概要

本ドキュメントは、dbatools PowerShellモジュールのInvoke-DbaQuery関数の機能設計を定義する。パラメータ化クエリをサポートしてT-SQLクエリ、スクリプト、ストアドプロシージャをSQL Serverインスタンスに対して実行する機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：カスタムSQLをSQL Server環境に対して実行するためのdbatools主要コマンド。レポート用データの抽出、複数サーバーへのスクリプトデプロイ、メンテナンスコマンドの実行など、多様なユースケースに対応。SQLインジェクション攻撃を防ぐための安全なパラメータ化クエリ実行を提供し、動的な値を使用したクエリを安全に実行できる。

**機能の利用シーン**：
- レポート作成のためのデータ抽出
- 複数サーバーへの同一スクリプトの一括実行
- ストアドプロシージャの呼び出し（入出力パラメータ対応）
- メンテナンススクリプトの実行
- テーブル値パラメータ（TVP）を使用した複雑なクエリ
- Always Encrypted列へのアクセス

**主要な処理内容**：
1. 文字列、ファイル、URL、またはSMOオブジェクトからクエリを取得
2. 接続確立（NonPooledConnectionで独立した接続管理）
3. パラメータ化クエリの構築（SqlParameterサポート）
4. クエリ実行（Invoke-DbaAsync経由）
5. 結果を指定フォーマット（DataRow/DataTable/DataSet/PSObject等）で出力

**関連システム・外部連携**：SQL Server Management Objects (SMO)、Microsoft.Data.SqlClient。可用性グループリスナーでのReadOnly intent接続サポート。

**権限による制御**：クエリ内容に応じた適切な権限が必要。ストアドプロシージャ実行にはEXECUTE権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに登録なし |

## 機能種別

クエリ実行 / データ取得

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstance[] | No | ターゲットSQL Serverインスタンス | ValueFromPipeline |
| SqlCredential | PSCredential | No | 接続資格情報 | - |
| Database | string | No | クエリ実行対象データベース | - |
| Query | string | Conditional | 実行するT-SQLコマンド | ParameterSetName="Query" |
| QueryTimeout | Int32 | No | クエリタイムアウト秒数 | - |
| File | object[] | Conditional | SQLスクリプトファイルパス/URL | ParameterSetName="File" |
| SqlObject | SqlSmoObject[] | Conditional | スクリプト化するSMOオブジェクト | ParameterSetName="SMO" |
| As | string | No | 出力フォーマット | ValidateSet |
| SqlParameter | psobject[] | No | パラメータ化クエリのパラメータ | - |
| CommandType | CommandType | No | コマンドタイプ（Text/StoredProcedure/TableDirect） | デフォルト: Text |
| AppendServerInstance | switch | No | 結果にサーバーインスタンス名を追加 | - |
| MessagesToOutput | switch | No | PRINTメッセージを出力に含める | - |
| InputObject | Database[] | No | パイプラインからのデータベースオブジェクト | ValueFromPipeline |
| ReadOnly | switch | No | ReadOnly application intentで接続 | - |
| NoExec | switch | No | 構文検証のみ実行しない | - |
| QuotedIdentifier | switch | No | SET QUOTED_IDENTIFIER ONを先頭に追加 | - |
| AppendConnectionString | string | No | 追加の接続文字列パラメータ | - |
| EnableException | switch | No | 例外をスローするか | - |

### 入力データソース

- QueryパラメータによるT-SQL文字列
- FileパラメータによるSQLファイル/URL
- SqlObjectパラメータによるSMOオブジェクト
- Get-DbaDatabase等からパイプラインで渡されるデータベースオブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| DataSet | System.Data.DataSet | Asパラメータ="DataSet"時の出力 |
| DataTable | System.Data.DataTable[] | Asパラメータ="DataTable"時の出力 |
| DataRow | System.Data.DataRow[] | Asパラメータ="DataRow"時の出力（デフォルト） |
| PSObject | PSObject | Asパラメータ="PSObject"時の出力 |
| PSObjectArray | PSObject[] | Asパラメータ="PSObjectArray"時の出力 |
| SingleValue | object | Asパラメータ="SingleValue"時の出力（単一スカラー値） |

### 出力先

- 標準出力（パイプライン）に指定フォーマットで出力
- AppendServerInstance指定時はServerInstance列を追加

## 処理フロー

### 処理シーケンス

```
1. beginブロック: パラメータ検証と準備
   ├─ SqlParameterの検証（ハッシュテーブルまたはSqlParameter）
   ├─ Invoke-DbaAsync用パラメータセット構築
   └─ File/SqlObject指定時のファイル読み込み/変換

2. processブロック開始
   ├─ Database/InputObject/SqlInstanceの排他チェック
   └─ パイプライン入力の処理

3. InputObject処理（データベースオブジェクトからの実行）
   ├─ アクセス可能チェック
   ├─ ConnectionContextの取得
   └─ Invoke-DbaAsync実行

4. SqlInstance処理（インスタンス直接指定の実行）
   ├─ 既存接続の再利用判定
   ├─ Connect-DbaInstance（必要時）
   └─ Invoke-DbaAsync実行

5. endブロック: クリーンアップ
   └─ 一時ファイルの削除
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{パラメータセット?}
    B -->|Query| C[Query文字列準備]
    B -->|File| D[ファイル読み込み]
    B -->|SMO| E[SMOオブジェクトスクリプト化]
    C --> F{入力ソース?}
    D --> F
    E --> F
    F -->|InputObject| G[データベースオブジェクト処理]
    F -->|SqlInstance| H[インスタンス接続]
    G --> I[ConnectionContext取得]
    H --> J{接続再利用可能?}
    J -->|Yes| K[既存接続使用]
    J -->|No| L[Connect-DbaInstance]
    I --> M[Invoke-DbaAsync]
    K --> M
    L --> M
    M --> N{Asフォーマット}
    N -->|DataRow| O[DataRow出力]
    N -->|PSObject| P[PSObject出力]
    N -->|SingleValue| Q[スカラー値出力]
    N -->|Other| R[指定形式出力]
    O --> S[終了]
    P --> S
    Q --> S
    R --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-174-01 | デフォルト出力フォーマット | Asパラメータ未指定時はDataRowで出力 | As未指定時 |
| BR-174-02 | パラメータ化クエリ必須 | 動的値を含むクエリはSqlParameterで渡す | セキュリティ要件 |
| BR-174-03 | 接続再利用条件 | Server SMOオブジェクト、ReadOnly未指定、Database一致、AppendConnectionString未指定、ConnectAsUserName空の場合のみ | 該当条件時 |
| BR-174-04 | NonPooled接続 | 新規接続時はNonPooledConnectionで作成 | 新規接続時 |

### 計算ロジック

接続再利用判定:
```powershell
$startedWithAnOpenConnection =
    ($instance.InputObject.GetType().Name -eq "Server") -and
    (-not $ReadOnly) -and
    (-not $Database -or $instance.InputObject.ConnectionContext.DatabaseName -eq $Database) -and
    (-not $AppendConnectionString) -and
    ($instance.InputObject.ConnectionContext.ConnectAsUserName -eq '')
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| SELECTクエリ | 任意 | SELECT | データ取得 |
| INSERT/UPDATE/DELETE | 任意 | INSERT/UPDATE/DELETE | データ変更 |
| ストアドプロシージャ | - | EXEC | プロシージャ実行 |
| DDLコマンド | - | CREATE/ALTER/DROP | スキーマ変更 |

### テーブル別操作詳細

クエリ内容に依存。本関数は汎用クエリ実行機能のため、特定のテーブル操作は定義されない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvalidArgument | SqlParameterが不正な形式 | ハッシュテーブルまたはSqlParameterを使用 |
| - | InvalidArgument | Database/InputObject/SqlInstanceの重複指定 | いずれか一つを指定 |
| - | ConnectionError | インスタンスへの接続失敗 | 接続情報を確認 |
| - | FileNotFound | 指定ファイルが存在しない | ファイルパスを確認 |
| - | QueryError | クエリ実行エラー | クエリ構文を確認 |

### リトライ仕様

リトライ機能は実装されていない。エラー発生時はStop-Functionで処理を中断。

## トランザクション仕様

トランザクション管理は呼び出し元の責任。BEGIN TRAN/COMMIT/ROLLBACKをクエリ内で使用可能。

## パフォーマンス要件

- QueryTimeoutで長時間実行クエリのタイムアウトを制御
- NonPooledConnectionによる接続管理
- ExcludePlanColumnでメモリ使用量を削減可能

## セキュリティ考慮事項

- SqlParameterによるパラメータ化クエリでSQLインジェクション防止
- SqlCredentialによる安全な認証をサポート
- Always Encrypted対応（Connect-DbaInstanceとの連携）
- ReadOnly application intentでセカンダリレプリカへのルーティング

## 備考

- Invoke-DbaAsyncが実際のクエリ実行を担当
- パイプライン操作でGet-DbaRegServerやGet-DbaDatabase連携可能
- テーブル値パラメータ（TVP）サポート

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

入力パラメータと出力フォーマットの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | 224-255行目: パラメータ定義とValidateSet |

**読解のコツ**: Asパラメータの各オプション（DataSet/DataTable/DataRow/PSObject/PSObjectArray/SingleValue）の違いを理解する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | 関数全体の流れを把握 |

**主要処理フロー**:
1. **257-266行目**: SqlParameterの検証
2. **268-296行目**: Invoke-DbaAsync用パラメータセット構築
3. **298-415行目**: File/SqlObject処理
4. **418-459行目**: InputObject（パイプライン）処理
5. **460-549行目**: SqlInstance直接指定処理

#### Step 3: 接続管理ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | 461-525行目: 接続再利用判定と新規接続 |

**主要処理フロー**:
- **500-505行目**: 接続再利用条件判定
- **510-524行目**: Connect-DbaInstance呼び出し（NonPooledConnection=true）

#### Step 4: 実際のクエリ実行を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Invoke-DbaAsync.ps1 | `private/functions/Invoke-DbaAsync.ps1` | Invoke-DbaAsyncの内部実装 |

### プログラム呼び出し階層図

```
Invoke-DbaQuery
    │
    ├─ beginブロック
    │      ├─ SqlParameter検証
    │      ├─ File処理 → Resolve-Path / Invoke-TlsWebRequest
    │      └─ SqlObject処理 → Export-DbaScript
    │
    ├─ processブロック
    │      ├─ InputObject処理
    │      │      ├─ ConnectionContext.GetDatabaseConnection
    │      │      └─ Invoke-DbaAsync
    │      │
    │      └─ SqlInstance処理
    │             ├─ 接続再利用判定
    │             ├─ Connect-DbaInstance (必要時)
    │             └─ Invoke-DbaAsync
    │
    └─ endブロック
           └─ 一時ファイル削除
```

### データフロー図

```
[入力]                          [処理]                              [出力]

Query (string) ──────────┐
File (path/URL) ─────────┼──▶ クエリ文字列構築
SqlObject (SMO) ─────────┘
                                    │
SqlParameter ────────────▶ パラメータ検証 ──▶ Invoke-DbaAsync
                                    │
SqlInstance ─────────────┐          │
InputObject ─────────────┼──▶ 接続確立 ───────┘
                                    │
                                    ▼
                           ┌───────┴───────┐
                           ▼               ▼
                     DataRow[]      PSObject[]
                           │               │
                           └───────┬───────┘
                                   ▼
                            パイプライン出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Invoke-DbaQuery.ps1 | `public/Invoke-DbaQuery.ps1` | ソース | メイン関数 |
| Invoke-DbaAsync.ps1 | `private/functions/Invoke-DbaAsync.ps1` | ソース | 実際のクエリ実行 |
| Connect-DbaInstance.ps1 | `public/Connect-DbaInstance.ps1` | ソース | SQL Server接続処理 |
| New-DbaSqlParameter.ps1 | `public/New-DbaSqlParameter.ps1` | ソース | SqlParameterオブジェクト生成 |
| Export-DbaScript.ps1 | `public/Export-DbaScript.ps1` | ソース | SMOオブジェクトのスクリプト化 |
