幽霊のようなクエリ:QueryDefの「隠し属性」による動的セキュリティの極致
Accessにおける`QueryDef`は、単なるクエリの保存先ではない。それはシステムの「実行エンジン」に直接介入するためのインターフェースだ。多くの開発者は「クエリを保存して、GUIで実行する」というレベルで止まっているが、真のアーキテクトは、実行の瞬間に生成し、痕跡を残さずに消滅させるという「一過性のアーキテクチャ」を設計する。
今回は、管理者権限の境界線上で機能する、セキュリティを担保した「隠しクエリ」の極限実装術を伝授する。
—
1. なぜ「隠し属性(Hidden)」なのか
Accessの`TableDef`や`QueryDef`には、Attributesプロパティが存在する。ここに`dbHiddenObject`定数を与えることで、ナビゲーションウィンドウから当該オブジェクトを物理的に隠蔽できる。
しかし、真の目的は「隠すこと」そのものにはない。「システムメタデータに永続化させない」ことにある。クエリを保存し続けることは、肥大化するデータベースの断片化を招き、セキュリティリスク(SQLの覗き見)を高めるだけだ。
我々が目指すのは、「メモリ上にのみ存在するクエリ」である。
—
2. 動的QueryDefの構築とメモリ最適化の真髄
`CreateQueryDef`メソッドに名前を与えず空文字(`””`)を渡すと、それは一時的なクエリとして生成される。これを適切に解放しなければ、Accessのエンジンはメモリリークを起こす。
以下のコードは、高セキュリティかつ低負荷な動的SQL実行のテンプレートだ。
‘ 伝説的なアーキテクトが教える、一過性クエリの実行パターン
Public Function ExecuteSecureQuery(ByVal sqlStatement As String, ParamArray params() As Variant) As Boolean
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim prm As DAO.Parameter
Dim i As Integer
Set db = CurrentDb
‘ 名前を空文字にすることで、ナビゲーションウィンドウには一切表示されない
‘ 一時的なQueryDefとして生成する
Set qdf = db.CreateQueryDef(“”, sqlStatement)
On Error GoTo Cleanup
‘ パラメータのバインド(SQLインジェクション対策)
If UBound(params) >= 0 Then
For i = 0 To UBound(params)
qdf.Parameters(i).Value = params(i)
Next i
End If
‘ 実行(戻り値が不要なアクションクエリを想定)
qdf.Execute dbFailOnError
ExecuteSecureQuery = True
Cleanup:
‘ 【重要】オブジェクトの明示的解放
‘ ここを疎かにするエンジニアがシステムを崩壊させる
If Not qdf Is Nothing Then
qdf.Close
Set qdf = Nothing
End If
Set db = Nothing
If Err.Number <> 0 Then
‘ エラーログ処理をここに実装
ExecuteSecureQuery = False
End If
End Function
—
3. レガシー環境でのAPI活用:プロセスの完全分離
もし、さらに強固なセキュリティを求めるなら、Windows APIを用いて「実行権限のコンテキスト」を切り替える必要がある。例えば、管理用クエリを実行する瞬間だけ、特定のログファイルを書き換えるAPIコールや、メモリ上のSQL文字列を暗号化する処理を噛ませる。
`kernel32`の`ZeroMemory`を用いて、処理後に変数のメモリ領域を0クリアする手法は、軍事レベルのセキュリティ要件では必須だ。
‘ メモリ上の機密情報を破棄するためのAPI定義
Private Declare PtrSafe Sub ZeroMemory Lib “kernel32” Alias “RtlZeroMemory” (dest As Any, ByVal numBytes As LongPtr)
‘ 使用例:SQL文字列を使い終わった後にメモリを消去
‘ Dim sql As String: sql = “…”
‘ ZeroMemory ByVal StrPtr(sql), LenB(sql)
—
4. アーキテクトの視点:システム管理への応用
この手法を応用すれば、以下のような堅牢な運用が可能になる。
- 動的権限管理: `CurrentUser()`やログインテーブルを参照し、条件を満たした時のみ`CreateQueryDef`を生成・実行。それ以外は即座にエラーを投げる。
- トレースの無効化: 保存されたクエリではないため、Accessのパフォーマンスアナライザやサードパーティの解析ツールに痕跡を残さない。
- インジェクション防御: `QueryDef`のパラメータオブジェクトを介すことで、VBA文字列結合によるSQLインジェクションを物理的に無効化する。
結論
「保存する」ことは怠惰である。真のエンジニアは、必要な時にのみ存在し、役目を終えれば霧のように消えるコードを書く。
Access VBAは、正しく扱えば現代のクラウドネイティブなAPI開発にも比肩する柔軟性を備えている。ナビゲーションウィンドウに並ぶクエリは、単なる「遺物」だ。動的生成こそが、システムの寿命を延ばし、守りを堅くする唯一の正攻法である。
コードに魂を込めろ。メモリの隅々まで掌握し、痕跡を残すな。それが、この領域における「プロフェッショナル」の流儀だ。
