Skip to content

Commit ea3e9a4

Browse files
committed
feat(readme): sqlalchemy section and example
1 parent e8c7b0e commit ea3e9a4

File tree

3 files changed

+165
-10
lines changed

3 files changed

+165
-10
lines changed

README.md

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,42 @@
55
</p>
66

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

1313

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

1922
---
2023

2124
[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.
2225

2326

24-
#### Compatibility with sqlite3 API
27+
## Compatibility with sqlite3 API
2528

26-
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.
29+
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.
2730

2831
- 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).
2932
- Source: [https://github.com/sqlitecloud/sqlitecloud-py](https://github.com/sqlitecloud/sqlitecloud-py)
3033
- Site: [https://sqlitecloud.io](https://sqlitecloud.io/developers)
3134

32-
## Example
35+
### Autocommit transactions: Difference between sqlitecloud and sqlite3
36+
37+
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.
38+
39+
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).
40+
41+
To manage transactions in sqlitecloud, you should explicitly use the `BEGIN`, `ROLLBACK`, `SAVEPOINT`, and `RELEASE` commands as needed.
42+
43+
## Installation and Usage
3344

3445
```bash
3546
$ pip install sqlitecloud
@@ -87,6 +98,81 @@ for row in cursor:
8798
print(row)
8899
```
89100

101+
## SQLite Cloud for SQLAlchemy (beta)
102+
103+
_This is an initial release, features and stability may not be guaranteed in all scenarios._
104+
105+
_If you encounter any bugs or issues, please feel free to open an issue on our GitHub repository._
106+
107+
We’ve implemented the initial support for `sqlitecloud` with [SQLAlchemy](https://www.sqlalchemy.org/), allowing you to utilize all standard SQLAlchemy operations and queries.
108+
For further information, please see the dedicated [REDAME](https://github.com/sqlitecloud/sqlitecloud-py/tree/%238-compatibility-sqlite3-dbapi2/sqlalchemy-sqlitecloud).
109+
110+
### Example
111+
112+
_The example is based on `chinook.sqlite` databse on SQLite Cloud_
113+
114+
Install the package:
115+
116+
```bash
117+
$ pip install sqlalchemy-sqlitecloud
118+
```
119+
120+
121+
```python
122+
import sqlalchemy
123+
from sqlalchemy import Column, ForeignKey, Integer, String
124+
from sqlalchemy.dialects import registry
125+
from sqlalchemy.orm import backref, declarative_base, relationship, sessionmaker
126+
127+
Base = declarative_base()
128+
129+
130+
class Artist(Base):
131+
__tablename__ = "artists"
132+
133+
ArtistId = Column("ArtistId", Integer, primary_key=True)
134+
Name = Column("Name", String)
135+
Albums = relationship("Album", backref=backref("artist"))
136+
137+
138+
class Album(Base):
139+
__tablename__ = "albums"
140+
141+
AlbumId = Column("AlbumId", Integer, primary_key=True)
142+
ArtistId = Column("ArtistId", Integer, ForeignKey("artists.ArtistId"))
143+
Title = Column("Title", String)
144+
145+
# SQLite Cloud connection string
146+
connection_string = "sqlitecloud://myhost.sqlite.cloud:8860/mydatabase.sqlite?apikey=myapikey"
147+
148+
engine = sqlalchemy.create_engine(connection_string)
149+
Session = sessionmaker(bind=engine)
150+
session = Session()
151+
152+
name = "John Doe"
153+
query = sqlalchemy.insert(Artist).values(Name=name)
154+
result_insert = session.execute(query)
155+
156+
title = "The Album"
157+
query = sqlalchemy.insert(Album).values(
158+
ArtistId=result_insert.lastrowid, Title=title
159+
)
160+
session.execute(query)
161+
162+
query = (
163+
sqlalchemy.select(Artist, Album)
164+
.join(Album, Artist.ArtistId == Album.ArtistId)
165+
.where(Artist.ArtistId == result_insert.lastrowid)
166+
)
167+
168+
result = session.execute(query).fetchone()
169+
170+
print("Artist Name: " + result[0].Name)
171+
print("Album Title: " + result[1].Title)
172+
173+
```
174+
175+
90176
## SQLite Cloud for Pandas DataFrame
91177

92178
[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.

sqlalchemy-sqlitecloud/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,65 @@ from sqlalchemy import create_engine
3737
engine = create_engine('sqlitecloud://mynode.sqlite.io?apikey=key1234')
3838
```
3939

40+
### Example
41+
42+
_The example is based on `chinook.sqlite` database on SQLite Cloud_
43+
44+
```python
45+
import sqlalchemy
46+
from sqlalchemy import Column, ForeignKey, Integer, String
47+
from sqlalchemy.dialects import registry
48+
from sqlalchemy.orm import backref, declarative_base, relationship, sessionmaker
49+
50+
Base = declarative_base()
51+
52+
53+
class Artist(Base):
54+
__tablename__ = "artists"
55+
56+
ArtistId = Column("ArtistId", Integer, primary_key=True)
57+
Name = Column("Name", String)
58+
Albums = relationship("Album", backref=backref("artist"))
59+
60+
61+
class Album(Base):
62+
__tablename__ = "albums"
63+
64+
AlbumId = Column("AlbumId", Integer, primary_key=True)
65+
ArtistId = Column("ArtistId", Integer, ForeignKey("artists.ArtistId"))
66+
Title = Column("Title", String)
67+
68+
# SQLite Cloud connection string
69+
connection_string = "sqlitecloud://myhost.sqlite.cloud:8860/mydatabase.sqlite?apikey=myapikey"
70+
71+
engine = sqlalchemy.create_engine(connection_string)
72+
Session = sessionmaker(bind=engine)
73+
session = Session()
74+
75+
name = "John Doe"
76+
query = sqlalchemy.insert(Artist).values(Name=name)
77+
result_insert = session.execute(query)
78+
79+
title = "The Album"
80+
query = sqlalchemy.insert(Album).values(
81+
ArtistId=result_insert.lastrowid, Title=title
82+
)
83+
session.execute(query)
84+
85+
query = (
86+
sqlalchemy.select(Artist, Album)
87+
.join(Album, Artist.ArtistId == Album.ArtistId)
88+
.where(Artist.ArtistId == result_insert.lastrowid)
89+
)
90+
91+
result = session.execute(query).fetchone()
92+
93+
print("Artist Name: " + result[0].Name)
94+
print("Album Title: " + result[1].Title)
95+
96+
```
97+
98+
4099

41100
# Run the Test Suite
42101

src/tests/integration/test_sqlalchemy.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,18 @@ def test_insert_and_select(connection_string, request):
6161
query = db.insert(Artist).values(Name=name)
6262
result_insert = session.execute(query)
6363

64-
query = db.select(Artist).where(Artist.ArtistId == result_insert.lastrowid)
65-
result_select = session.execute(query).fetchone()
64+
title = "The Album" + str(uuid.uuid4())
65+
query = db.insert(Album).values(ArtistId=result_insert.lastrowid, Title=title)
66+
session.execute(query)
6667

67-
assert result_select[0].ArtistId == result_insert.lastrowid
68-
assert result_select[0].Name == name
68+
query = (
69+
db.select(Artist, Album)
70+
.join(Album, Artist.ArtistId == Album.ArtistId)
71+
.where(Artist.ArtistId == result_insert.lastrowid)
72+
)
73+
74+
result = session.execute(query).fetchone()
75+
76+
assert result[0].ArtistId == result_insert.lastrowid
77+
assert result[0].Name == name
78+
assert result[1].Title == title

0 commit comments

Comments
 (0)