CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/sqlite-python-best-practices

SQLite best practices for Python -- PRAGMAs per connection, context manager transactions, parameterized queries, row_factory, executemany, FK indexes

92

1.73x
Quality

90%

Does it follow best practices?

Impact

97%

1.73x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-5/

{
  "context": "Tests whether the agent proactively applies SQLite best practices when building a Python recipe app with complex relationships (one-to-many, many-to-many, cascading deletes). The task never mentions PRAGMAs, WAL mode, context managers, foreign keys, or parameterized queries. The agent should set up foreign_keys=ON (critical for CASCADE to work), use context managers for atomic recipe+ingredient creation, and apply proper indexing.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "WAL mode enabled",
      "description": "Connection setup sets PRAGMA journal_mode=WAL",
      "max_score": 10
    },
    {
      "name": "Foreign keys ON",
      "description": "Connection setup sets PRAGMA foreign_keys=ON. This is critical -- without it, ON DELETE CASCADE will silently not work, and the task requires cascading deletes for ingredients",
      "max_score": 12
    },
    {
      "name": "Busy timeout set",
      "description": "Connection setup sets PRAGMA busy_timeout to a positive value",
      "max_score": 5
    },
    {
      "name": "Row factory configured",
      "description": "Connection sets conn.row_factory = sqlite3.Row for dict-like access",
      "max_score": 8
    },
    {
      "name": "Context manager for recipe creation",
      "description": "Creating a recipe with its ingredients uses 'with conn:' context manager for atomic commit/rollback -- recipe and all ingredients saved together or not at all",
      "max_score": 12
    },
    {
      "name": "Context manager for recipe update",
      "description": "Updating a recipe and replacing its ingredients uses 'with conn:' for atomicity -- delete old ingredients + insert new ones + update recipe in one transaction",
      "max_score": 10
    },
    {
      "name": "Parameterized queries throughout",
      "description": "ALL queries use ? placeholders -- no f-strings or string concatenation for SQL values, especially in the search/filter queries",
      "max_score": 10
    },
    {
      "name": "ON DELETE CASCADE on ingredients FK",
      "description": "The ingredients table defines REFERENCES recipes(id) ON DELETE CASCADE so deleting a recipe removes its ingredients",
      "max_score": 8
    },
    {
      "name": "Indexes on FK and search columns",
      "description": "Explicit indexes on foreign key columns (ingredients.recipe_id, recipe_tags junction table columns)",
      "max_score": 8
    },
    {
      "name": "Many-to-many via junction table",
      "description": "Tags implemented as a separate tags table with a recipe_tags junction table (not as a comma-separated TEXT column)",
      "max_score": 7
    },
    {
      "name": "Connection properly closed",
      "description": "Connections are closed in finally blocks or managed via Flask teardown_appcontext / context manager",
      "max_score": 5
    },
    {
      "name": "executemany for bulk ingredient inserts",
      "description": "Inserting multiple ingredients uses executemany() rather than a loop of individual execute() calls",
      "max_score": 5
    }
  ]
}

evals

tile.json