PLエンジン(PL Engine)とSQLエンジン(SQL Engine)は相互に連携して動作します。SQLはPLエンジンに直接アクセスでき、例えばユーザー定義関数を使用するSQL文を記述できます。PLはSPIインターフェースを通じてSQLエンジンにアクセスし、式の計算やSQL文の実行を行います。
両者の相互作用の関係は以下の図のようになります:

PL Engineは、Parser、Resolver、Code Generator、Compiler、Executor、PL Cacheの6つのモジュールで構成されています。その中で、Parser、Resolver、Code Generator、Compilerが一連のPLコンパイルプロセスを形成します。以下の図のようになります:

Parser(構文解析器)
ParserはPL構文を解析し、構文木(Parse Tree)を生成します。PLエンジンとSQLエンジンはそれぞれ独立したParserを実装していますが、両者は冗長な処理を避けるようにしています。OBServerでは、クエリ文字列はまずPL Parserに入り解析され、SQL文であることが検出された場合はSQLエンジンに渡されて解析されます。
Resolver(意味解析器)
Resolverは意味解析を行い、変数のスコープのチェックや静的SQLにおけるデータオブジェクトのスキーマなどを確認し、各PL文に対応する抽象構文木AST構造とグローバルなAST構造を生成します。ASTはPL定義の基本情報や生成されたグローバルシンボルテーブル、グローバルラベルテーブル、グローバル例外テーブルなどの情報を格納しています。各文のASTには、これらのグローバルテーブルへの論理的な参照情報が記録されています。
Code Generator(コードジェネレータ)
Code GeneratorはLLVMが提供するインターフェースを使用してASTをさらに翻訳し、ASTツリーをIR中間コードに変換します。IRコードは翻訳プロセスが正しいかどうかを検証するために使用できます。
Compiler(コンパイラ)
CompilerはインスタントコンパイルJITを通じてIRコードを機械語に変換し、実行可能なPLオブジェクトとして出力します。
Executor(エグゼキュータ)
Executorは、コンパイルされたPL実行可能オブジェクトと入力パラメータに基づいて実行環境を構築し、関数ポインタを呼び出して関数の結果を取得します。
PL Cache(実行計画キャッシュモジュール)
PL CacheはPL Engineの内部メカニズムであり、PL Engineは外部に対してIDによるProcedureまたはFunctionの実行インターフェースを統一的に提供します。外部からはPLのキャッシュメカニズムを理解する必要はなく、PL Engineを通じてPLを実行するだけで済みます。PL CacheはHashテーブルであり、Key(ProcedureまたはFunctionのID)によってValue(PL実行オブジェクト)を検索し、Schemaへのアクセスを通じてPL実行可能オブジェクトの有効性をチェックします。無効な場合は即座に削除されます。PL Cacheは毎回PLを再コンパイルすることを回避し、PLの実行効率を向上させるために使用されます。そのため、匿名ブロック(Anonymous Block)にはキャッシュを使用する必要はありません。
PL Engineは外部にExecuteインターフェースを提供しており、そのパラメータにはPL ID、実行パラメータparams、実行環境Context、実行結果Result(Functionにのみ有効)が含まれます。まず、IDに基づいてPL Cache内にコンパイル済みのPL実行可能オブジェクトが存在するかどうかを検索します。存在する場合は、Versionが利用可能かどうかをさらにチェックします。PL Cacheに利用可能なPL実行可能オブジェクトがない場合は、コンパイルプロセスを呼び出してコンパイルし、コンパイル後の結果をPL CacheにキャッシュしてからExecutorに渡して実行します。コンパイルの結果はバイナリコードのメモリアドレスであり、Executorはこのメモリアドレスを関数ポインタに変換し、実行パラメータと実行環境を渡して結果を得ます。