リレーショナル スキーマにうまく適合する一連の Python データ構造を管理する方法を探していますが、実際のデータベースや SQL の解析によるオーバーヘッドはありません。データ量はメモリに収まるほど小さいと想定できます (たとえば、100 万を超える要素を含む構造体はありません)。
最も重要なことは、外部キー制約を自動的に適用したいということです。外部キー制約違反でアサーションの失敗をトリガーするだけで十分です。それは常にプログラミングエラーです。
これは、私が達成したいことの実際の例です。これを行うコードはありますが、自動外部キー制約チェックがないと、エラーが発生しやすくなり、アサートが混乱します。
(これらは、機械語プログラムの実行トレースを分析するためのコードのデータ構造です。興味深いことに、ロガー プログラムは、それぞれの一意の (previous_instruction_addr、current_instruction_addr、stack_pointer_change) タプルを 1 回出力します。)
instrs
: set(int) (機械語命令のアドレス)next_instrs
: dict(int -> set(int))、命令 ( にある必要がありますinstrs
) を一連の命令 (すべてが にある必要があります) にマッピングする辞書instrs
。関係的には、instrs
×の部分集合instrs
。stk_changes
: dict((int,int) -> set(int)) 、命令のペア (命令のペアは にある必要がありますnext_instrs
) をスタック ポインター レジスタの一連の変更にマッピングする辞書jumps
: set((int,int))、あるnext_instrs
命令から別の命令へのジャンプ (関数呼び出しまたは関数からの戻りを含む) と見なされる関係のサブセット。実際には、「この命令はどこにジャンプしますか?」という形式の両方のクエリを作成できるようにする必要があるため、現在これを 2 つの dict として実装しています。および「この命令にジャンプする命令は何ですか?」。calls
: set((int,int))、そのサブセットjumps
は関数呼び出しです。rets
: set((int,int))、そのサブセットはjumps
関数から返されます。basic_blocks
: set(int)、のサブセットinstrs
; 基本ブロックの最初のアドレス(最初の命令でのみ実行が開始されるコードのブロック、つまり、途中へのジャンプはなく、最後の命令でのみ終了する、つまり途中からのジャンプはありません)containing_bb
: dict(int -> int)、各命令を含む基本ブロック。instrs
×の部分集合basic_blocks
functions
: set(int)、関数の開始と見なされる基本ブロック。のサブセットbasic_blocks
。function_calls_by_bb
: dict(int -> int)、基本ブロックによって呼び出される関数;basic_blocks
×の部分集合functions
等々; あなたはアイデアを得る。
私が本質的に探しているのは、このすべての構造を管理し、すべての外部キー制約を自動的に適用する方法です。たとえば、が のメンバーでないbasic_blocks.add(something)
場合、エラーで失敗したいと考えています。同様に、がまだ参照されている場合は失敗したいと思います。明らかに、これらすべての構造のアサーションとメソッドを記述することは、たとえば SQL データベース スキーマの外部キー制約と比較して、不必要に冗長でエラーが発生しやすくなります。something
instrs
basic_blocks.remove(something)
something
function_calls_by_bb
add()
remove()
私は現在、メモリ内の sqlite データベースを使用して sqlalchemy で遊んでいます。これにより、制約をうまく説明できますが、理想的には、データベース エンジンを含まない、より軽量なものを探しています。(データベース エンジンは、最終的には私がやっていることを実行するための適切な方法かもしれませんが、現在、代替手段を評価しています。)
あるいは、このような構造を管理する別の方法が考えられる場合は、それらについても興味があります。