検索/高速なデータベースのコードを、速さと互換性を落とさずに直す

高速なデータベースのコードを、速さと互換性を落とさずに直す

Java・SQL・Rust・ネイティブコード・CIにまたがる、速さ重視のデータベースをAIに直させる時に使う。コードの書き方、NULLの扱いとメモリの後片付け、クエリのテスト、失敗の調べ方、プルリクエストとビルドの決まりを示し、完了と言う前の最終チェックで締める。

このAIルールを使うには
## モジュールの境目を保ち、メモリを確保しないデータの流れを守る - storage engine、SQL engine、network protocol、utility、worker queue、logging、background task、benchmark、compatibility test、exampleのmodule boundaryを明示的に維持する。 - production codeをbenchmark、build utility、example、platform wrapperから分離する。 - 入れ子のclient repositoryまたはsubmoduleを、独自のcommitとcompatibility targetを持つ独立repositoryとして扱う。 - behaviorを変える前に、server startup、storage engine、SQL compiler、table reader、table writerのどれが正しいentry pointか特定する。 - query executionとingestion中のzero-allocation data pathを保護する。 - architectureが要求する場合はobject pool、reusable buffer、column-oriented storage、vectorized execution、native accelerationを優先する。 - projectがperformance-critical algorithmを内製する方針なら、third-party runtime dependencyを導入しない。 - memory、platform、failure riskに見合うoperationだけにnative codeを限定する。 ## Javaのクラスメンバーを決まった順に並べ、古いJava向けクライアントとの互換性を守る - class memberをstaticまたはinstanceの種別とvisibilityでまとめ、各group内でalphabetical orderを保つ。 - decorative section groupを作らず、新しいfieldとmethodを正しいsort位置へ挿入する。 - Javaのsection heading代わりとなるbanner commentを絶対に追加しない。 - main moduleが対応するmodern language featureを使う。enhanced switch、multiline string、pattern variableなどが該当する。 - compatibility moduleでは古いlanguage targetを守り、main moduleのsyntaxを旧Java release向けclientへ混入させない。 - boolean variable、field、methodには内容に応じて`is`または`has`prefixを付ける。 - logging pipelineがUnicode punctuationやsymbolを確実に表示できない場合、log messageを厳密にASCIIだけで書く。 - 既存cleanup utilityと連携する場合は、generic object arrayよりprojectのresource-aware collection typeを使う。 - 新しいabstractionを導入する前に、既存のnaming、ownership、allocation patternに従う。 ## NULLの扱いを決め、エラーの時もメモリを必ず片付ける - column data、expression result、SQL statement、intermediate stateのNULL behaviorを明示的に決める。 - 「まだ初期化されていない」を表すNULL sentinelと、実データのNULLを区別する。 - すべてのallocationとcloseable resourceをsuccess、error、cancellation、early returnの各pathで追跡する。 - listとcloseable elementにはrepository所定のcleanup helperを一貫して使う。 - leak preventionをtestだけの関心事ではなくdesign requirementとして扱う。 - native memoryをallocateするtestにはmemory-leak assertionを追加する。 - native memoryをallocateしないことを証明できる狭いunit testではleak harnessを省略してよい。 - success pathだけでなく、関連するすべてのerror pathでcleanupを検証する。 - 便利なcontainerやhelperの背後にownershipの曖昧さを隠さない。 ## クエリのテストは、結果を読み直す厳しいチェックで書く - 旧式のsingle-pass print-and-compare helperではなく、正規のfluent query assertion frameworkを優先する。 - deterministic queryでは、2回目のcursor pass、size cross-check、variable-column check、関連するfactory-property assertionを必須にする。 - 1回だけのassertionはprojectionが再読時に本当に不安定な場合だけ使い、その理由を明記する。 - 正当な不安定性にはseedなしrandom functionやtime-varying functionが含まれる。 - DDLなどのnon-query statementはnon-query execution pathで実行する。 - optimizer behaviorが契約の一部なら、frameworkのplan helperでexecution planをassertする。 - dialectが対応する場合、複数のtest rowを1つのINSERT statementで追加する。 - 長いSQLとmultiline expected resultにはmultiline stringを使う。 - SQL keywordは一貫して書き、原則としてuppercaseを使う。 - syntaxが対応する場合、5桁以上のliteralではunderscoreで桁を区切る。 ## SQLの方言に合わせ、エラーの位置を問題の文字ぴったりに指す - dimensionalityがcolumn typeに含まれる場合、multidimensional array typeを別々のtypeとして扱う。 - 同等のcast表現を混在させず、dialectが推奨するcast syntaxを一貫して使う。 - numeric separatorの対応をparser、implementation code、testの間で一致させる。 - standard SQL featureが存在すると決めつけず、未対応operationを文書化してtestする。 - 行単位の消去に対応しない場合は、application logicでsoft deletionを明示的にmodel化する。 - partition単位のdrop operationと行単位の消去は作用範囲と安全性が異なるため区別する。 - 報告するSQL error positionはexpressionの先頭ではなく、問題を起こした正確なcharacterを指すようにする。 - parser errorではmessageと正確なpositionの両方をtestする。 - syntax、semantic、type、executionのerrorを区別したまま保つ。 ## 落ちたテストは、証拠がそろうまで本物のバグとして調べる - red test、failed CI job、unexpected log entryを、evidenceが反証するまでlive defectとして扱う。 - 「pre-existing」「flaky」「unrelated」「known issue」は仮説であり、結論ではない。 - 関連baselineで再現し、version historyを調べ、timing constraintを測定し、authoritative upstream reportを確認する。 - evidenceが別の結論を強制した後に限り、そのfailureを対象外にする。 - 別のreviewerが検証できるよう、classificationの根拠となったevidenceを報告する。 - green rerunだけをfailureが無害だった唯一の証拠にしない。 - 複数のchangeが同じCI lineageを共有する場合はinteraction failureを調べる。 - diagnosisに必要なlog、failing input、最小のreliable reproductionを維持する。 - 証明されたcauseだけにfixを絞り、そのfixがなければ失敗するregression testを追加する。 ## ブランチとプルリクエストを、マージの方式とCIの手間に合わせる - branchとpull requestのstrategyをrepositoryのmerge modelとCI costに合わせる。 - squash-merge workflowでは、破棄されるbranch historyを整えるために時間を使わない。 - cosmetic historyだけのためにprior commitを書き換えたりforce pushしたりせず、明確なfix-up commitを追加する。 - 分割によって長いCI run、flake exposure、merge coordinationが増える場合は、関連fixをまとめる。 - userが要求した場合、またはchangeを独立してmergeもしくはrevertする必要がある場合にだけ分割する。 - 既存pull requestを更新する時はremote headと同期し、そのbranchへchangeを追加してmetadataを更新する。 - 同じchange lineageのvalidationを再実行するためだけに、2つ目のpull requestを開かない。 - repository policyが別branchをcanonical review stateとして定める場合、review用worktreeやcheckout branchを作らない。 - diffだけが必要ならbranchを切り替えずにpull request diffを取得する。 - nested repository内部を先にcommitしてから、parentのsubmodule pointerを記録する。 ## プルリクエストとコミットに、良い点も悪い点も同じ重さで書く - repository所定のpull request title conventionを使い、descriptionをend userに意味のある内容にする。 - positive effect、negative effect、regression、tradeoffを同じ強さで記述する。 - sales language、superlative、selective metric、decorative emphasisを避ける。 - 修正対象issueはpull request body冒頭で所定のclosing formを使って参照する。 - commit titleは短く、descriptiveにし、repository所定のstyleへ合わせる。 - titleの繰り返しではなく、changeを説明する実質的なcommit bodyを含める。 - checkboxやcheck markが禁止されている場合、test planにはplain bulletを使う。 - change domainとtitleに合うlabelを付ける。 - commit、pull request、code commentではactive voiceを使う。 - passive constructionに隠さず、動作主体であるclass、method、caller、componentを明記する。 ## 環境を確かめてから、いちばん小さい範囲でビルドとテストをする - build前に必要なlanguage runtime、build tool、architecture、environment variableを確認する。 - 現在のchangeを証明できる最小build profileを選び、webまたはnative artifactが影響を受ける時はより完全なprofileを使う。 - local artifact cacheに古いclientまたはlibraryが残る可能性がある場合はdependent moduleをrebuildする。 - parallel buildが干渉する場合、高costなtest invocationをsequentialに実行する。 - 最も狭い関連test classまたはmethodから始め、riskとrepository policyに応じて広げる。 - compilationだけをruntime behaviorの証明として扱わない。 - 対応するstartup pathでserverを検証し、直接影響するendpointまたはinterfaceを確認する。 - build artifactを指定されたmodule-owned locationへ置く。 - buildが止まった時は、失敗した正確なcommandと最初のactionable errorを記録する。 ## Rustの警告をなくし、JNI越しのpanicでJVMが落ちないようにする - Rust作業の完了前にcrate rootからformatting、all-target compilation、lint、library testを実行する。 - mandatory checkすべてでエラー0件・警告0件を必須にする。 - testを追加または変更した後はcoverageを測定する。 - uncovered lineごとにtestを追加するか、到達不能であることを証明してinvariantを明示的にmarkする。 - file由来またはexternal input由来のdataに`unwrap()`や`expect()`を絶対に使わない。 - recoverable failureは`Result`、`Option`、language標準のerror propagationで伝える。 - JNIをまたぐRust panicはrecoveryなしにJVM全体をabortさせる可能性があることを忘れない。 - repository所定のrelease configurationでnative C/C++ libraryをbuildし、expected artifactを確認する。 - FFI ownership、lifetime、alignment、error conversionを明示的な契約として扱う。 - changeが影響するsupported platformすべてでboundary failureをtestする。 ## ヒープの確保を避け、速くなったかはベンチマークで測る - zero-GC behaviorがarchitecture requirementであるdata pathではheap allocationを避ける。 - bufferとpooled objectを再利用し、ownership transferを明示する。 - compressionとvectorized operationがlayoutに依存する場合、analytical dataをcolumn単位で保存する。 - SIMD、memory management、platform-specific optimizationを狭いnative boundaryの内側に置く。 - storage、parsing、planning、code generation、execution、protocol handling、background workを分離する。 - allocationとcleanup behaviorを理解しtestしている場合にだけcustom collectionを使う。 - performance changeはintuitionではなくrepresentative benchmarkで測定する。 - optimizationにはcorrectness test、resource check、documented tradeoffを組み合わせる。 - 未測定のspeedupを得るためにcompatibilityやerror precisionを弱めない。 ## 完了と言う前に、最後の差分を確かめて結果を報告する - final diffでmember ordering、compatibility boundary、NULL behavior、resource ownership、logへの意図しないUnicode混入を確認する。 - changeが影響するJava、SQL、Rust、native、integrationのcheckを実行する。 - deterministic queryがstrong reread assertion pathを使っていることを確認する。 - external inputがunrecoverable native panicを引き起こせないことを確認する。 - 調査したfailureにevidence-backed classificationと報告済みreproductionがあることを確認する。 - pull request metadata、label、test plan、commit text、issue referenceがrepository policyに合うことを確認する。 - nested repositoryとparent pointerが正しい順序でcommitされていることを確認する。 - mandatory checkにerrorまたはwarningが残る間は完了を主張しない。 - 実行したcommand、observed result、remaining risk、意図的に未testとしたscopeを報告する。