{"product_id":"dev-08-the-database-schema-reviewer","title":"The Database Schema Reviewer","description":"\u003cdiv class=\"verax-spec-sheet\"\u003e\n  \u003cdiv class=\"verax-spec-header\"\u003e\n    \u003cdiv class=\"verax-spec-title\"\u003eSPECIFICATION\u003c\/div\u003e\n    \u003cdiv class=\"verax-spec-id\"\u003eDEV-08\u003c\/div\u003e\n  \u003c\/div\u003e\n  \u003cdiv class=\"verax-spec-grid\"\u003e\n    \u003cdiv class=\"verax-spec-item\"\u003e\n\u003cspan class=\"verax-spec-label\"\u003eCATEGORY\u003c\/span\u003e\u003cspan class=\"verax-spec-value\"\u003eTechnical\u003c\/span\u003e\n\u003c\/div\u003e\n    \u003cdiv class=\"verax-spec-item\"\u003e\n\u003cspan class=\"verax-spec-label\"\u003eFOCUS\u003c\/span\u003e\u003cspan class=\"verax-spec-value\"\u003eNormal-form diagnosis, Karwin's named SQL antipatterns \u0026amp; the B-tree leftmost-prefix indexing rule\u003c\/span\u003e\n\u003c\/div\u003e\n    \u003cdiv class=\"verax-spec-item\"\u003e\n\u003cspan class=\"verax-spec-label\"\u003eBEST FOR\u003c\/span\u003e\u003cspan class=\"verax-spec-value\"\u003eReviewing schema and index design against specific, named patterns instead of vague normalization advice\u003c\/span\u003e\n\u003c\/div\u003e\n    \u003cdiv class=\"verax-spec-item\"\u003e\n\u003cspan class=\"verax-spec-label\"\u003eMETHODOLOGY\u003c\/span\u003e\u003cspan class=\"verax-spec-value\"\u003eCodd's normal forms · SQL Antipatterns catalog · B-tree leftmost-prefix rule\u003c\/span\u003e\n\u003c\/div\u003e\n    \u003cdiv class=\"verax-spec-item\"\u003e\n\u003cspan class=\"verax-spec-label\"\u003eFORMAT\u003c\/span\u003e\u003cspan class=\"verax-spec-value\"\u003e.md + .txt\u003c\/span\u003e\n\u003c\/div\u003e\n    \u003cdiv class=\"verax-spec-item\"\u003e\n\u003cspan class=\"verax-spec-label\"\u003eCOMPATIBLE MODELS\u003c\/span\u003e\u003cspan class=\"verax-spec-value\"\u003eAll (ChatGPT, Claude, Gemini, Grok + more)\u003c\/span\u003e\n\u003c\/div\u003e\n    \u003cdiv class=\"verax-spec-item\" style=\"border-bottom: none; padding-bottom: 0;\"\u003e\n\u003cspan class=\"verax-spec-label\"\u003eSKILL LEVEL\u003c\/span\u003e\u003cspan class=\"verax-spec-value\"\u003eAdvanced\u003c\/span\u003e\n\u003c\/div\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"verax-comp-grid\"\u003e\n  \u003cdiv class=\"ai-box ai-general card\"\u003e\n    \u003cdiv class=\"chat-header\"\u003eGENERAL ASSISTANT\u003c\/div\u003e\n    \u003cdiv class=\"chat-window\"\u003e\n      \u003cdiv class=\"msg-row msg-user\"\u003e\n        \u003cdiv class=\"msg-avatar msg-avatar-user\"\u003e\u003csvg width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\u003e\u003cpath d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"\u003e\u003c\/path\u003e\u003ccircle cx=\"12\" cy=\"7\" r=\"4\"\u003e\u003c\/circle\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"msg-content\"\u003eWe have a \u0026amp;quot;comments\u0026amp;quot; table with a \u0026amp;quot;commentable_id\u0026amp;quot; and \u0026amp;quot;commentable_type\u0026amp;quot; column, so it can attach to either a \u0026amp;quot;post\u0026amp;quot; or a \u0026amp;quot;photo\u0026amp;quot;. Is that a reasonable design?\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"msg-row msg-ai ai-row\"\u003e\n        \u003cdiv class=\"msg-avatar msg-avatar-ai\"\u003e\u003csvg width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\u003e\u003cpath d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"msg-content msg-content-ai\"\u003eYou should normalize your database and add indexes to make queries faster.\u003c\/div\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"chat-input\"\u003e\n      \u003cinput type=\"text\" class=\"message-input\" placeholder=\"Type your message here...\" readonly\u003e\n      \u003cbutton class=\"send-button\"\u003eSend\u003c\/button\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n  \u003cdiv class=\"ai-box ai-verax card\"\u003e\n    \u003cdiv class=\"chat-header\"\u003eDEV-08 — THE DATABASE SCHEMA REVIEWER\u003c\/div\u003e\n    \u003cdiv class=\"chat-window\"\u003e\n      \u003cdiv class=\"msg-row msg-user\"\u003e\n        \u003cdiv class=\"msg-avatar msg-avatar-user\"\u003e\u003csvg width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\u003e\u003cpath d=\"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2\"\u003e\u003c\/path\u003e\u003ccircle cx=\"12\" cy=\"7\" r=\"4\"\u003e\u003c\/circle\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"msg-content\"\u003eWe have a \u0026amp;quot;comments\u0026amp;quot; table with a \u0026amp;quot;commentable_id\u0026amp;quot; and \u0026amp;quot;commentable_type\u0026amp;quot; column, so it can attach to either a \u0026amp;quot;post\u0026amp;quot; or a \u0026amp;quot;photo\u0026amp;quot;. Is that a reasonable design?\u003c\/div\u003e\n      \u003c\/div\u003e\n      \u003cdiv class=\"msg-row msg-ai ai-row\"\u003e\n        \u003cdiv class=\"msg-avatar msg-avatar-ai\"\u003e\u003csvg width=\"18\" height=\"18\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewbox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\u003e\u003cellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\"\u003e\u003c\/ellipse\u003e\u003cpath d=\"M3 5v6c0 1.66 4.03 3 9 3s9-1.34 9-3V5\"\u003e\u003c\/path\u003e\u003cpath d=\"M3 11v6c0 1.66 4.03 3 9 3s9-1.34 9-3v-6\"\u003e\u003c\/path\u003e\u003c\/svg\u003e\u003c\/div\u003e\n        \u003cdiv class=\"msg-content msg-content-ai\"\u003eThat's a well-known pattern called a \u003cspan class=\"syn-kw\"\u003ePolymorphic Association\u003c\/span\u003e, and the tradeoff worth knowing is specific: because commentable_id has to be able to reference either the posts table or the photos table depending on commentable_type, the database can't enforce a real foreign-key constraint on it - so nothing stops a commentable_id from pointing at a row that's been deleted or never existed, and that integrity check has to live in application code instead, where it's much easier to miss.\u003cbr\u003e\u003cbr\u003e\n          If you only ever have two or three commentable types and they're stable, a common, more constraint-friendly alternative is separate nullable foreign-key columns with a check constraint ensuring exactly one is set - more columns, but the database can actually enforce correctness.\u003c\/div\u003e\n      \u003c\/div\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"chat-input\"\u003e\n      \u003cinput type=\"text\" class=\"message-input\" placeholder=\"Type your message here...\" readonly\u003e\n      \u003cbutton class=\"send-button\"\u003eSend\u003c\/button\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e","brand":"Expeona","offers":[{"title":"Default Title","offer_id":60643527197006,"sku":"DEV-08","price":9.0,"currency_code":"RON","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/1074\/0088\/8654\/files\/DEV-08.svg?v=1788451453","url":"https:\/\/expeona.com\/products\/dev-08-the-database-schema-reviewer","provider":"Expeona","version":"1.0","type":"link"}