{"id":27603273,"url":"https://github.com/ggabriel96/resql","last_synced_at":"2026-05-01T19:33:31.541Z","repository":{"id":40275405,"uuid":"360739885","full_name":"ggabriel96/resql","owner":"ggabriel96","description":"A database auditing and recovery library based on SQLAlchemy","archived":false,"fork":false,"pushed_at":"2022-12-08T08:47:58.000Z","size":244,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-22T19:14:43.996Z","etag":null,"topics":["auditing","database","recovery","sql","sqlalchemy"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ggabriel96.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-23T02:26:38.000Z","updated_at":"2021-10-25T01:53:54.000Z","dependencies_parsed_at":"2022-08-28T11:11:27.912Z","dependency_job_id":null,"html_url":"https://github.com/ggabriel96/resql","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ggabriel96%2Fresql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ggabriel96%2Fresql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ggabriel96%2Fresql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ggabriel96%2Fresql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ggabriel96","download_url":"https://codeload.github.com/ggabriel96/resql/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250306629,"owners_count":21408926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auditing","database","recovery","sql","sqlalchemy"],"created_at":"2025-04-22T19:14:48.440Z","updated_at":"2026-05-01T19:33:26.485Z","avatar_url":"https://github.com/ggabriel96.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# resql\n\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![codecov](https://codecov.io/gh/ggabriel96/resql/branch/main/graph/badge.svg?token=AOVOWTNSMW)](https://codecov.io/gh/ggabriel96/resql)\n\nresql (pronounced like \"rescue\") is a database auditing and recovery library based on SQLAlchemy.\nIt mainly provides two things: a way to register changes to objects (the change log), and a way to register executed queries (the query log).\n\n**This is way too early in development, so don't use it in production.**\nFor example, the recovery features, like restoring a database using the logged queries, are not yet available.\nAdditionally, there are many, many tests yet to be implemented, and the interface is not stable.\n\n## The change log\n\nAs the name implies, the change log focuses on establishing a complete history of an object's changes.\nIt currently registers the following information:\n\n- the name of the table in which it occurred\n- the primary key (PK) of the object that changed (just an integer, so `id` is a required column)\n- the diff of the change, in JSON\n- the type of the change (insert, update, or delete)\n- the date and time of the change\n- any extra information provided during setup\n\nTo setup change logs, first map the database table to the respective Python class (via `map_default` in this example).\nThen, simply call `log_changes`:\n\n```python\nfrom resql.auditing import log_changes\nfrom resql.change_log import map_default\n\naudit_registry = map_default()\nlog_changes(of=session, to=audit_engine)\n```\n\nIt is just a shortcut to creating a `ChangeLogger` and adding the event listener.\nThe function signature is as follows:\n\n```python\ndef log_changes(\n    *,\n    of: Union[Session, sessionmaker],\n    to: Engine,\n    extra: Optional[dict[str, Any]] = None,\n) -\u003e ChangeLogger\n```\n\n## The query log\n\nThe main goal of the query log is to aid database recovery by logging every query that executed.\nIn order to do this, it registers the following information:\n\n- the type of the query, taken directly from SQLAlchemy's: `Select`, `Insert`, `Update`, etc.\n- the dialect of the query, e.g. `sqlite+pysqlite`\n- the compiled statement that was executed\n- the compiled parameters of the statement\n- the date and time the query was executed\n- any extra information provided during setup\n\nWith this data, one should be able to programmatically re-run these queries again from a given starting point.\n\nTo setup query logs, first map the database table to the respective Python class (via `map_default` in this example).\nThen, simply call `log_queries`:\n\n```python\nfrom resql.auditing import log_queries\nfrom resql.query_log import map_default\n\nrecovery_registry = map_default()\nlog_queries(of=production_engine, to=recovery_engine)\n```\n\nSimilarly to `log_changes`, it is just a shortcut to creating a `QueryLogger` and adding the event listener.\nThe function signature is as follows:\n\n```python\ndef log_queries(\n    *,\n    of: Union[Engine, Connection],\n    to: Engine,\n    extra: Optional[dict[str, Any]] = None,\n) -\u003e QueryLogger\n```\n\n## The `extra` parameter\n\nThe `extra` parameter is the extra information that will be added to each log.\nNote that the change log can be registered on a `Session` or a `sessionmaker`, and the query log can be registered on an `Engine` or a `Connection`.\nRegistering them on a `Session` or a `Connection`, respectively, adds more flexibility to what `extra`s will be saved, since one could want them to vary under certain conditions.\nOne possible use case is to add information about the current user that is logged in and causing these changes or queries.\nUsing them on `sessionmaker` or `Engine` is more like global loggers.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fggabriel96%2Fresql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fggabriel96%2Fresql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fggabriel96%2Fresql/lists"}