Skip to content

#8 compatibility dbapi2/sqlite3 #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e80d32b
fix(test): use random table name
danielebriggi Aug 7, 2024
e65a892
feat(dbapi): commit and rollback
danielebriggi Aug 8, 2024
efb53de
feat(adapters): text factory and adapters
danielebriggi Aug 13, 2024
2ad05fd
fix(types): respect types from SCSP
danielebriggi Aug 14, 2024
3637f01
feat(adapters): support to __conform__() method
danielebriggi Aug 14, 2024
8b9c53f
feat(decltypes): support to parse_decltypes
danielebriggi Aug 14, 2024
9b72f71
feat(parse-columns): support to PARSE_COLUMNS
danielebriggi Aug 14, 2024
93e268b
feat(row-object): support to Row object for row_factory
danielebriggi Aug 16, 2024
4f01ce6
fix(parse-colnames): parse colnames from `[decltype]` in py>=3.7
danielebriggi Aug 16, 2024
0ba234d
feat(workflow): run tests on the latest py security maintained release
danielebriggi Aug 16, 2024
43546b8
feat(statement): server sude support to prepared statements
danielebriggi Aug 19, 2024
57696f9
feat(rowcount): support to rowcount, lastworid and total_changes
danielebriggi Aug 19, 2024
c36efcf
feat(context-manager): support to context manager for transactions
danielebriggi Aug 19, 2024
b7ff349
feat(param-style): workaround to support param-style in statements
danielebriggi Aug 20, 2024
b25b140
feat(dbapi2): compatibility specs
danielebriggi Aug 22, 2024
7b1b435
feat(errors): map SQLite errors in DBAPI2 exceptions
danielebriggi Aug 22, 2024
8e09861
feat(sqlalchemy): initial version of sqlalchemy dialect
danielebriggi Aug 23, 2024
eb043d9
feat(sqlalchemy): organized provisioning for tests
danielebriggi Aug 23, 2024
e8c7b0e
fix(tests): expected errors, escaping
danielebriggi Aug 23, 2024
ea3e9a4
feat(readme): sqlalchemy section and example
danielebriggi Aug 26, 2024
e703f10
fix(tests): improve casual failures
danielebriggi Aug 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .devcontainer/py3.6-dev/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ ADD https://dl.yarnpkg.com/debian/pubkey.gpg /etc/apt/trusted.gpg.d/yarn.asc

RUN chmod +r /etc/apt/trusted.gpg.d/*.asc && \
echo "deb http://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list

COPY install-legacy-extensions.sh /usr/local/bin/install-legacy-extensions.sh
RUN chmod +x /usr/local/bin/install-legacy-extensions.sh
11 changes: 3 additions & 8 deletions .devcontainer/py3.6-dev/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,24 @@
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",
"postCreateCommand": "install-legacy-extensions.sh",

// Configure tool-specific properties.
// Py3.6 support (switch extensions to `pre-release` and `install another version`):
// Pylance v2022.6.30
// Python v2022.8.1
// Python Debugger v2023.1.XXX (pre-release version | debugpy v1.5.1)
// Python Debugger v2023.1.12492010 (pre-release version | debugpy v1.5.1)
// Black Formatter v2022.2.0
// Isort v2022.1.11601002 (pre-release)
"customizations": {
"vscode": {
"extensions": [
"littlefoxteam.vscode-python-test-adapter",
"jkillian.custom-local-formatters",
"ms-python.vscode-pylance",
"ms-python.python",
"ms-python.debugpy",
"ms-python.black-formatter",
"ms-python.isort",
"ms-toolsai.jupyter"
]
}
}
},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
Expand Down
7 changes: 7 additions & 0 deletions .devcontainer/py3.6-dev/install-legacy-extensions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

code --install-extension "[email protected]"
code --install-extension "[email protected]"
code --install-extension "[email protected]"
code --install-extension "[email protected]"
code --install-extension "[email protected]"
38 changes: 38 additions & 0 deletions .devcontainer/py3.7/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/python
{
"name": "Python 3.7",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:3.7",
"features": {
"ghcr.io/warrenbuckley/codespace-features/sqlite:1": {}
},

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",

// Configure tool-specific properties.
"customizations": {
"vscode": {
"extensions": [
"littlefoxteam.vscode-python-test-adapter",
"jkillian.custom-local-formatters",
"ms-python.vscode-pylance",
"ms-python.python",
"ms-python.debugpy",
"ms-python.black-formatter",
"ms-python.isort",
"ms-toolsai.jupyter"
]
}
}

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
3 changes: 2 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.6", "3.12"]
# last supported for sqlitecloud, last security maintained, last release
python-version: ["3.6", "3.8", "3.12"]

steps:
- uses: actions/checkout@v4
Expand Down
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
build/
experiments/
sdk/
venv/
.venv*/
main.dSYM/
.env
*.pyc
Expand All @@ -12,6 +12,11 @@ main.dSYM/
.DS_Store

.idea
SqliteCloud.egg-info
sqlitecloud.egg-info

playground.ipynb

src/tests/assets/*-shm
src/tests/assets/*-wal

chinook.sqlite
100 changes: 93 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,43 @@
<img src="https://sqlitecloud.io/social/logo.png" height="300" alt="SQLite Cloud logo">
</p>

![Build Status](https://github.com/sqlitecloud/sqlitecloud-py/actions/workflows/deploy.yaml/badge.svg "Build Status")
[![codecov](https://codecov.io/github/sqlitecloud/python/graph/badge.svg?token=38G6FGOWKP)](https://codecov.io/github/sqlitecloud/python)
![Build Status](https://github.com/sqlitecloud/sqlitecloud-py/actions/workflows/test.yaml/badge.svg "Build Status")
[![codecov](https://codecov.io/gh/sqlitecloud/sqlitecloud-py/graph/badge.svg?token=38G6FGOWKP)](https://codecov.io/gh/sqlitecloud/sqlitecloud-py)
![PyPI - Version](https://img.shields.io/pypi/v/sqlitecloud?link=https%3A%2F%2Fpypi.org%2Fproject%2FSqliteCloud%2F)
![PyPI - Downloads](https://img.shields.io/pypi/dm/sqlitecloud?link=https%3A%2F%2Fpypi.org%2Fproject%2FSqliteCloud%2F)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/sqlitecloud?link=https%3A%2F%2Fpypi.org%2Fproject%2FSqliteCloud%2F)


- [Driver for SQLite Cloud](#driver-for-sqlite-cloud)
- [Example](#example)
- [SQLite Cloud](#)
- [Compatibility with sqlite3 API](#compatibility-with-sqlite3-api)
- [Autocommit transactions: Difference between sqlitecloud and sqlite3](#autocommit-transactions-difference-between-sqlitecloud-and-sqlite3)
- [Installation and Usage](#installation-and-usage)
- [SQLite Cloud loves sqlite3](#sqlite-cloud-loves-sqlite3)
- [SQLite Cloud for SQLAlchemy (beta)](#sqlite-cloud-for-sqlalchemy-beta)
- [SQLite Cloud for Pandas DataFrame](#sqlite-cloud-for-pandas-dataframe)

---

[SQLite Cloud](https://sqlitecloud.io) is a powerful Python package that allows you to interact with the SQLite Cloud database seamlessly. It provides methods for various database operations. This package is designed to simplify database operations in Python applications, making it easier than ever to work with SQLite Cloud.


#### Compatibility with sqlite3 API
## Compatibility with sqlite3 API

We aim for full compatibility with the Python built-in [sqlite3](https://docs.python.org/3.6/library/sqlite3.html) API (based on Python [PEP 249](https://peps.python.org/pep-0249)), with the primary distinction being that our driver connects to SQLite Cloud databases. This allows you to migrate your local SQLite databases to SQLite Cloud without needing to modify your existing Python code that uses the sqlite3 API.
We aim for full compatibility with the Python built-in [sqlite3](https://docs.python.org/3.6/library/sqlite3.html) API (based on Python DBAPI 2.0 [PEP 249](https://peps.python.org/pep-0249)), with the primary distinction being that our driver connects to SQLite Cloud databases. This allows you to migrate your local SQLite databases to SQLite Cloud without needing to modify your existing Python code that uses the sqlite3 API.

- Documentation: Our API closely follows the sqlite3 API. You can refer to the sqlite3 documentation for most functionality. The list of implemented features are documented [here](https://github.com/sqlitecloud/sqlitecloud-py/issues/8).
- Source: [https://github.com/sqlitecloud/sqlitecloud-py](https://github.com/sqlitecloud/sqlitecloud-py)
- Site: [https://sqlitecloud.io](https://sqlitecloud.io/developers)

## Example
### Autocommit transactions: Difference between sqlitecloud and sqlite3

In `sqlitecloud`, autocommit is **always enabled**, and we currently do not support disabling it. This means that the `isolation_level` is always set to `None`, resulting in autocommit being permanently on.

This behavior differs from the sqlite3 Python module, where autocommit can be controlled (see details in the section [Controlling Transactions](https://docs.python.org/3.6/library/sqlite3.html#controlling-transactions) in the official documentation).

To manage transactions in sqlitecloud, you should explicitly use the `BEGIN`, `ROLLBACK`, `SAVEPOINT`, and `RELEASE` commands as needed.

## Installation and Usage

```bash
$ pip install sqlitecloud
Expand Down Expand Up @@ -87,6 +98,81 @@ for row in cursor:
print(row)
```

## SQLite Cloud for SQLAlchemy (beta)

_This is an initial release, features and stability may not be guaranteed in all scenarios._

_If you encounter any bugs or issues, please feel free to open an issue on our GitHub repository._

We’ve implemented the initial support for `sqlitecloud` with [SQLAlchemy](https://www.sqlalchemy.org/), allowing you to utilize all standard SQLAlchemy operations and queries.
For further information, please see the dedicated [REDAME](https://github.com/sqlitecloud/sqlitecloud-py/tree/%238-compatibility-sqlite3-dbapi2/sqlalchemy-sqlitecloud).

### Example

_The example is based on `chinook.sqlite` databse on SQLite Cloud_

Install the package:

```bash
$ pip install sqlalchemy-sqlitecloud
```


```python
import sqlalchemy
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.dialects import registry
from sqlalchemy.orm import backref, declarative_base, relationship, sessionmaker

Base = declarative_base()


class Artist(Base):
__tablename__ = "artists"

ArtistId = Column("ArtistId", Integer, primary_key=True)
Name = Column("Name", String)
Albums = relationship("Album", backref=backref("artist"))


class Album(Base):
__tablename__ = "albums"

AlbumId = Column("AlbumId", Integer, primary_key=True)
ArtistId = Column("ArtistId", Integer, ForeignKey("artists.ArtistId"))
Title = Column("Title", String)

# SQLite Cloud connection string
connection_string = "sqlitecloud://myhost.sqlite.cloud:8860/mydatabase.sqlite?apikey=myapikey"

engine = sqlalchemy.create_engine(connection_string)
Session = sessionmaker(bind=engine)
session = Session()

name = "John Doe"
query = sqlalchemy.insert(Artist).values(Name=name)
result_insert = session.execute(query)

title = "The Album"
query = sqlalchemy.insert(Album).values(
ArtistId=result_insert.lastrowid, Title=title
)
session.execute(query)

query = (
sqlalchemy.select(Artist, Album)
.join(Album, Artist.ArtistId == Album.ArtistId)
.where(Artist.ArtistId == result_insert.lastrowid)
)

result = session.execute(query).fetchone()

print("Artist Name: " + result[0].Name)
print("Album Title: " + result[1].Title)

```


## SQLite Cloud for Pandas DataFrame

[Pandas](https://pypi.org/project/pandas/) is a Python package for data manipulation and analysis. It provides high-performance, easy-to-use data structures, such as DataFrame.
Expand Down
Loading
Loading