{"id":14974094,"url":"https://github.com/g4brym/sqlify","last_synced_at":"2026-03-11T11:01:23.675Z","repository":{"id":57470566,"uuid":"434741831","full_name":"G4brym/sqlify","owner":"G4brym","description":"A simple sql builder with migrations based on standard Python type hints","archived":false,"fork":false,"pushed_at":"2023-12-20T14:14:58.000Z","size":101,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-27T22:32:45.569Z","etag":null,"topics":["database","migration-tool","migrations","postgres","postgresql","psycopg2","python","query","query-builder","sql","sql-builder","sqlite3"],"latest_commit_sha":null,"homepage":"https://sqlify.massadas.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/G4brym.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-03T21:45:40.000Z","updated_at":"2024-04-15T23:05:45.000Z","dependencies_parsed_at":"2025-02-12T09:39:53.333Z","dependency_job_id":null,"html_url":"https://github.com/G4brym/sqlify","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/G4brym/sqlify","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/G4brym%2Fsqlify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/G4brym%2Fsqlify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/G4brym%2Fsqlify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/G4brym%2Fsqlify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/G4brym","download_url":"https://codeload.github.com/G4brym/sqlify/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/G4brym%2Fsqlify/sbom","scorecard":{"id":53738,"data":{"date":"2025-08-11","repo":{"name":"github.com/G4brym/sqlify","commit":"ccf32ace8c414d6cfdde3fc10aa13d4240255878"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/G4brym/sqlify/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/G4brym/sqlify/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/G4brym/sqlify/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/G4brym/sqlify/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/G4brym/sqlify/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/G4brym/sqlify/test.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/publish.yml:29","Warn: pipCommand not pinned by hash: .github/workflows/test.yml:33","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-15T00:13:58.402Z","repository_id":57470566,"created_at":"2025-08-15T00:13:58.402Z","updated_at":"2025-08-15T00:13:58.402Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30379264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T06:09:32.197Z","status":"ssl_error","status_checked_at":"2026-03-11T06:09:17.086Z","response_time":84,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["database","migration-tool","migrations","postgres","postgresql","psycopg2","python","query","query-builder","sql","sql-builder","sqlite3"],"created_at":"2024-09-24T13:49:56.612Z","updated_at":"2026-03-11T11:01:23.655Z","avatar_url":"https://github.com/G4brym.png","language":"Python","readme":"# [Sqlify](https://github.com/g4brym/Sqlify)\nThis project is a fork from [pg_simple](https://github.com/masroore/pg_simple), that tries to implement a standard SQL\nwith python type hinting interface.\nThis fork also implements extra parameters like having or with queries.\nOther goals for this project is to support other types of databases like sqlite.\n\n[Read full documentation here](https://sqlify.massadas.com/)\n\nThe [Sqlify](https://github.com/g4brym/Sqlify) module provides a simple standardized interface while keeping the \nbenefits and speed of using raw queries over `psycopg2` or `sqlite3`\nThis module is ment to work as a query builder, and you must provide your own integrations and session pooling if you want.\n\n`sqlify` is not intended to provide ORM-like functionality, rather to make it easier to interact with the database from \npython code for direct SQL access using convenient wrapper methods.\n\nThe `sqlify` module provides:\n\n* Python typed interface that can scale from just basic queries to some complex queries, for example using the\n[PostgreSQL With](https://www.postgresql.org/docs/9.1/queries-with.html)\n* Python API to wrap basic SQL functionality: select, update, delete, join et al\n* Query results as python dict objects\n* Inserts/Updates/Deletes returning data as dict objects or the affected rows count\n* Auto commit/rollback when finishing one or multiple queries\n* Database migration tools\n* Typer cli for migration commands\n* Bulk insert (WIP)\n* On the fly error prevention when developing with a smart IDE like pycharm (due to the advanced type hinting)\n* Debug logging support\n\n\n## Installation\n\nWith `pip` or `easy_install`:\n\n```pip install sqlify```\n\nor:\n\n```easy_install sqlify```\n\nor from the source:\n\n```python setup.py install```\n\n\n## 30 Seconds Quick-start Guide\n\n* Step 1: Connect to the database of your choice\n* Step 2: Using the Session class pass through the connection\n* Step 3: Enjoy your queries\n\nHere's a pseudo-example to illustrate the basic concepts:\n\n```python\nimport sqlite3\nfrom sqlify import Session\n\nconn = sqlite3.connect('my_test.db')\nwith Session(conn, autocommit=True) as sqlify:\n    rest = sqlify.fetchone(\n        table=\"test\",\n        fields=\"column_1\",\n    )\n```\n\n\n## Basic Usage\n\n### Connecting to the posgtresql server\n\nThe following snippet will connect to the posgtresql server and allocate a cursor:\n\n```python\nimport psycopg2\nfrom sqlify import Session\n\nconn = psycopg2.connect(\"host=localhost dbname=test user=postgres password=postgres\")\nwith Session(conn, autocommit=True) as sqlify:\n    rest = sqlify.fetchone(\n        table=\"test\",\n        fields=\"column_1\",\n    )\n```\n\nBy default `psycopg2` generates result sets as `collections.namedtuple` objects (using `psycopg2.extras.NamedTupleCursor`). \nBut because `sqlify` is connection agnostic you can easily modify it to use the `DictCursor` that returns a `Dict` object\n\n```python\nimport psycopg2\nfrom psycopg2.extras import DictCursor\n\nconn = psycopg2.connect(\"host=localhost dbname=test user=postgres password=postgres\", cursor_factory=DictCursor)\n```\n\nIf you don't like context based interfaces (aka [with statement](https://www.geeksforgeeks.org/with-statement-in-python/))\nor it doesn't fit your architecture you can also assign it to a variable and use it as you did expect.\nBut remember that by using it this way you lost the auto-commit/rollback feature and auto-close of the database connection\n\n```python\nsqlify = Session(conn, autocommit=True).session\nrest = sqlify.fetchone(\n    table=\"test\",\n    fields=\"column_1\",\n)\n\nsqlify.commit()\nsqlify.close()\n```\n\n### Fetching a single record\n\n```python\nwith Session(conn, autocommit=True) as sqlify:\n    book = sqlify.fetchone(\n        table='books', \n        fields=\"*\",\n        where=(\n            \"published = %(publish_date)s\",\n            dict(\n                publish_date=datetime.date(2002, 2, 1),\n            ),\n        ),\n    )\n                   \nprint(f\"{book.name} was published on {book.published}\")\n```\n\n### Fetching multiple records\n\n```python\nfrom sqlify import Order\n\nwith Session(conn, autocommit=True) as sqlify:\n    books = sqlify.fetchone(\n        table='books',\n        fields=['name AS n', 'genre AS g'],\n        where=(\n            [\n                \"published BETWENN %(since)s and %(to)s\",\n                \"gender = %(gender)s\",\n            ],\n            dict(\n                since=datetime.date(2005, 2, 1),\n                to=datetime.date(2009, 2, 1),\n                gender=\"fiction\",\n            ),\n        ),\n        order=(\"published\", Order.DESC),\n        limit=5,\n        offset=2,\n    )\n\nfor book in books:\n    print(f\"{book.name} was published on {book.published}\")\n```\n\n### Raw SQL execution\n\nIn raw queries you can use both `list` and `dict` annotations\n\n```python\nwith Session(conn, autocommit=True) as sqlify:\n    sqlify.execute('SELECT tablename FROM pg_tables WHERE schemaname=%s and tablename=%s', ['public', 'books'])\n    sqlify.execute('SELECT name FROM books WHERE author=%(author)s', {\"author\": \"Andre\"})\n```\n\n### Inserting rows\n\n```python\nwith Session(conn, autocommit=True) as sqlify:\n    for i in range(1, 10):\n        sqlify.insert(\n            table=\"books\",\n            data=dict(\n                name=f\"Book Name vol. {i}\",\n                price=1.23 * i,\n                genre=\"fiction\",\n                published=f\"{2000 + i}-{i}-1\",\n            ),\n        )\n\n    # DB commit is already called when the session context exits without any exception\n    # You can disable this with autocommit=False\n```\n\n### Updating rows\n\n```python\nfrom sqlify import RawSQL\n\nwith Session(conn, autocommit=True) as sqlify:\n    affected_rows = sqlify.update(\n        table=\"books\",\n        where=(\n            \"published = %(published)s\",\n            dict(\n                published=datetime.date(2001, 1, 1)\n            ),\n        ),\n        data=dict(\n            genre=\"non-fiction\",\n            modified=RawSQL(\"now()\"),\n        ),\n    )\n    \n    # Commit is implicit\n    \nprint(f\"Lines updated in this query: {affected_rows}\")\n```\n\n### Deleting rows\n\n```python\nwith Session(conn, autocommit=True) as sqlify:\n    deleted_rows = sqlify.delete(\n        table=\"books\",\n        where=(\n            \"published \u003e= %(published)s\",\n            dict(published=datetime.date(2005, 1, 31)),\n        ),\n    )\n\n    # Commit is implicit\n\nprint(f\"Lines deleted in this query: {deleted_rows}\")\n```\n\n### Dropping and creating tables\n\n```python\nwith Session(conn, autocommit=True) as sqlify:\n    sqlify.drop('books')\n\n    sqlify.create('books',\n        '''\n        \"id\" SERIAL NOT NULL,\n        \"type\" VARCHAR(20) NOT NULL,\n        \"name\" VARCHAR(40) NOT NULL,\n        \"price\" MONEY NOT NULL,\n        \"published\" DATE NOT NULL,\n        \"modified\" TIMESTAMP(6) NOT NULL DEFAULT now()\n        '''\n    )\n\n    sqlify.execute('''ALTER TABLE \"books\" ADD CONSTRAINT \"books_pkey\" PRIMARY KEY (\"id\")''')\n\n    # Commit is implicit\n```\n\n### Emptying a table or set of tables\n\n```python\nwith Session(conn, autocommit=True) as sqlify:\n    sqlify.truncate('tbl1')\n    sqlify.truncate('tbl2, tbl3', restart_identity=True, cascade=True)\n\n    # Commit is implicit\n```\n\n### Inserting/updating/deleting rows with return value\n\n```python\nwith Session(conn, autocommit=True) as sqlify:\n    row = sqlify.insert(\n        table=\"books\",\n        data=dict(\n            name=f\"Book Name vol. {i}\",\n            price=1.23 * i,\n            genre=\"fiction\",\n            published=f\"{2000 + i}-{i}-1\",\n        ),\n        returning=\"id\",\n    )\nprint(row.id)\n\nwith Session(conn, autocommit=True) as sqlify:\n    rows = sqlify.update(\n        table=\"books\",\n        where=(\n            \"published = %(published)s\",\n            dict(\n                published=datetime.date(2001, 1, 1)\n            ),\n        ),\n        data=dict(\n            genre=\"non-fiction\",\n            modified=RawSQL(\"now()\"),\n        ),\n        returning=\"*\",\n    )\nfor row in rows:\n    print(row.modified)\n\nwith Session(conn, autocommit=True) as sqlify:\n    rows = sqlify.delete(\n        table=\"books\",\n        where=(\n            \"published \u003e= %(published)s\",\n            dict(published=datetime.date(2005, 1, 31)),\n        ),\n        returning=\"name\",\n    )\nfor row in rows:\n    print(row.name)\n```\n\n### Explicit database transaction management\n\n```python\nwith Session(conn, autocommit=False) as sqlify:\n    try:\n        sqlify.execute('Some SQL statement')\n        sqlify.commit()\n    except:\n        sqlify.rollback()\n```\n\n### Implicit database transaction management\n\n```python\nwith Session(conn, autocommit=True) as sqlify:\n    sqlify.execute('Some SQL that trows an error')\n    # Rollback will automatically be called and the exception will continue down the execution tree\n```\n\nThe above transaction will be rolled back automatically should something goes wrong.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg4brym%2Fsqlify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fg4brym%2Fsqlify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fg4brym%2Fsqlify/lists"}