Skip to content

Commit 515012c

Browse files
committed
update
2 parents e7b12ee + eb6a001 commit 515012c

9 files changed

Lines changed: 1097 additions & 17 deletions

File tree

sqlite-cloud/_nav.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ const sidebarNav: SidebarNavStruct = [
1717
{ title: "Next.js", filePath: "quick-start-next", type: "inner", level: 1 },
1818
{ title: "Django", filePath: "quick-start-django", type: "inner", level: 1 },
1919
{ title: "Flask", filePath: "quick-start-flask", type: "inner", level: 1 },
20+
{ title: "SQLAlchemy", filePath: "quick-start-sqlalchemy-orm", type: "inner", level: 1 },
2021
{ title: "Streamlit", filePath: "quick-start-streamlit", type: "inner", level: 1 },
2122
{ title: "PHP / Laravel", filePath: "quick-start-php-laravel", type: "inner", level: 1 },
2223
{ title: "Gin", filePath: "quick-start-gin", type: "inner", level: 1 },
24+
{ title: "Tutorials", type: "inner", level: 0 },
25+
{ title: "Geopoly", filePath: "tutorial-geopoly", type: "inner", level: 1 },
2326

2427
{ title: "Platform", type: "secondary", icon: "docs-plat" },
2528
{ title: "Edge Functions", filePath: "edge-functions", type: "inner", level: 0 },
@@ -140,6 +143,8 @@ const sidebarNav: SidebarNavStruct = [
140143
{ title: "React", ref: "/docs/quick-start-react", type: "inner", level: 2 },
141144
{ title: "Node.js", ref: "/docs/quick-start-node", type: "inner", level: 2 },
142145
{ title: "Next.js", ref: "/docs/quick-start-next", type: "inner", level: 2 },
146+
{ title: "Tutorials", type: "inner", level: 1 },
147+
{ title: "Using SQLite Extensions - Geopoly", ref: "/docs/tutorial-geopoly", type: "inner", level: 2 },
143148
{ title: "Classes", type: "inner", level: 1 },
144149
{ title: "Database", filePath: 'sqlite-cloud/sdks/js/classes/Database', type: "inner", level: 2 },
145150
{ title: "SQLiteCloudConnection", filePath: 'sqlite-cloud/sdks/js/classes/SQLiteCloudConnection', type: "inner", level: 2 },
@@ -158,6 +163,7 @@ const sidebarNav: SidebarNavStruct = [
158163
{ title: 'Introduction', type: "inner", filePath: "sdk-python-introduction", level: 1 },
159164
{ title: "Django", ref: "/docs/quick-start-django", type: "inner", level: 1 },
160165
{ title: "Flask", ref: "/docs/quick-start-flask", type: "inner", level: 1 },
166+
{ title: "SQLAlchemy", ref: "/docs/quick-start-sqlalchemy-orm", type: "inner", level: 1 },
161167

162168
{ title: "Go", type: "inner", level: 0 },
163169
{ title: 'Introduction', type: "inner", filePath: "sdk-go-introduction", level: 1 },

sqlite-cloud/platform/edge-functions.mdx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Turning on linearizable reads ensures strong consistency, but may introduce some
1616

1717
## Getting Started
1818
1. Navigate to the Edge Functions page from your dashboard.
19-
1. Under "Development", select "Edge Function", then click the "Create" button.
20-
1. Write and test your function.
19+
2. Under "Development", select "Edge Function", then click the "Create" button.
20+
3. Write and test your function.
2121
1. Select the database you want to access and an API key if necessary
2222
2. When you're finished, click deploy.
2323

@@ -31,6 +31,24 @@ return {
3131
}
3232
```
3333

34+
### Authorization
35+
Edge functions that access your SQLite databases must be authorized via API key. You can automatically authorize an edge function on every call by assigning it an API key via the "API KEY" dropdown.
36+
37+
If no API key is assigned, an API key must be sent in the request url as a query parameter (`?apikey=YOUR_API_KEY`) or as an attribute in the request body (`{ apikey: YOUR_API_KEY }`).
38+
39+
### Execution
40+
41+
Edge functions can be called via HTTP GET and POST methods. You can pass additional values to your edge function in two ways:
42+
- Query parameters: Accessible via `request.params`
43+
- Request body: Accessible via `request.data`
44+
45+
### Testing
46+
You may test the execution of edge functions by clicking the "Test" command.
47+
48+
You are not required to supply an API key when testing your edge function in the console. The function will run using the dashboard user privileges.
49+
50+
51+
3452
## Guides
3553
### Interacting with your Database
3654
Use the global `connection` object to access and manipulate your database.

sqlite-cloud/platform/vector.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Every SQLite Cloud database comes with the `sqlite-vec` extension pre-installed.
1212

1313
Using sqlite-vec is similar to using full-text search in SQLite. Declare a "virtual table" with vector columns, insert data with normal INSERT INTO statements, and query with normal SELECT statements.
1414

15-
`sqlite-vec` is currently built and optimized for brute-force vector search. This means there is no approximate nearest neighbor search available, limiting the number of vectors that can be searched in a reasonable amount of time.
15+
`sqlite-vec` is currently built and optimized for brute-force vector search. This means there is no approximate nearest neighbor search available at this time.
1616

1717
## Usage
1818
### Create a vector table
@@ -100,7 +100,7 @@ insert into vec_items_slim
100100
```
101101

102102
## Performance considerations
103-
Free SQLite Cloud plans are not optimized for vector workloads. To speak to the team about upgrading your plan, [please reach out](https://www.sqlitecloud.io/support).
103+
Free SQLite Cloud plans are not optimized for large-scale vector workloads. To speak to the team about upgrading your plan, [please reach out](https://www.sqlitecloud.io/support).
104104

105105
## Next Steps
106106
Combined with [edge functions](/docs/edge-functions), SQLite Cloud's vector search capabilities make it a great choice for serverless RAG applications.

sqlite-cloud/quick-start-apollo-graphql.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ const resolvers = {
139139
};
140140
```
141141

142-
- Lastly, pass the GraphQLL type definitions and resolvers into a new ApolloServer instance, and start the server.
142+
- Lastly, pass the GraphQL type definitions and resolvers into a new ApolloServer instance, and start the server.
143143
```js
144144
const server = new ApolloServer({ typeDefs, resolvers });
145145

sqlite-cloud/quick-start-react-native.mdx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ cd sqlc-quickstart
2626
eas init --id {id}
2727
```
2828

29-
3. **Install the SQLite Cloud JS SDK**
29+
3. **Install the SQLite Cloud JS SDK and peer dependencies**
3030

3131
```bash
32-
npm install @sqlitecloud/drivers
32+
npm install @sqlitecloud/drivers react-native-tcp-socket react-native-fast-base64
3333
```
3434

3535
4. **Query data**
@@ -46,12 +46,14 @@ export default function App() {
4646

4747
useEffect(() => {
4848
async function getAlbums() {
49-
const db = new Database(
50-
'<your-connection-string>'
51-
);
49+
const db = new Database('<your-connection-string>');
5250

5351
const result =
54-
await db.sql`USE DATABASE chinook.sqlite; SELECT albums.AlbumId as id, albums.Title as title, artists.name as artist FROM albums INNER JOIN artists WHERE artists.ArtistId = albums.ArtistId LIMIT 20;`;
52+
await db.sql`USE DATABASE chinook.sqlite;
53+
SELECT albums.AlbumId as id, albums.Title as title, artists.name as artist
54+
FROM albums
55+
INNER JOIN artists
56+
WHERE artists.ArtistId = albums.ArtistId LIMIT 20;`;
5557

5658
setAlbums(result);
5759
}
@@ -92,13 +94,14 @@ const styles = StyleSheet.create({
9294

9395
5. **Run your app**
9496

97+
Expo run iOS
9598
```bash
96-
npm start
99+
npx expo prebuild && npx expo run:ios
97100
```
98101

99-
- To see your app:
100-
- On iOS, use the Camera app to scan the QR code.
101-
- On Android, download and use the Expo Go app to scan the QR code.
102-
- On web, visit the localhost link.
102+
Expo run Android
103+
```bash
104+
npx expo prebuild && npx expo run:android
105+
```
103106

104107
And that's it! You've successfully built a React Native app that reads data from a SQLite Cloud database.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
title: SQLAlchemy ORM Quick Start Guide
3+
description: Get started with SQLite Cloud using SQLAlchemy ORM in FastAPI.
4+
category: getting-started
5+
status: publish
6+
slug: quick-start-sqlalchemy-orm
7+
---
8+
9+
In this Quick Start, we will show you how to get started with SQLite Cloud by building a FastAPI backend that connects to and reads from a SQLite Cloud database using SQLAlchemy.
10+
11+
NOTE that FastAPI framework:
12+
- does NOT require you to use a relational database or any database at all.
13+
- CAN work with any ORM library (including SQLAlchemy) or database (including SQLite, which comes pre-installed in Python and is a database supported by SQLAlchemy).
14+
- code is MINIMAL in the example below. Most of the code is standard SQLAlchemy and framework-agnostic.
15+
16+
---
17+
18+
1. **Set up a SQLite Cloud account**
19+
- If you haven't already, [sign up for a SQLite Cloud account](https://sqlitecloud.io/register) and create a new project.
20+
- In this guide, we will use the sample datasets that come pre-loaded with SQLite Cloud.
21+
22+
2. **Create a new Python project**
23+
- You should have the latest Python version (3) installed locally.
24+
25+
```bash
26+
mkdir sqlalchemy-quickstart
27+
cd sqlalchemy-quickstart
28+
29+
# open the project in VSCode / another editor
30+
code .
31+
32+
python3 -m venv .venv
33+
. .venv/bin/activate
34+
```
35+
36+
3. **Install dependencies**
37+
- Run this command from your current directory:
38+
39+
```bash
40+
pip install "fastapi[standard]" sqlalchemy sqlalchemy-sqlitecloud
41+
```
42+
43+
- Do NOT remove the quotes around the FastAPI package.
44+
- `sqlalchemy-sqlitecloud` includes `sqlitecloud`, so no need to install the latter separately.
45+
46+
4. **App setup**
47+
- From your current directory, create a sub-directory `fastapi_sqlc_app` with an empty `__init__.py` file to indicate the new sub-directory is a package.
48+
- NOTE: We will create all remaining project files in this sub-directory.
49+
50+
```bash
51+
mkdir fastapi_sqlc_app
52+
cd fastapi_sqlc_app
53+
touch __init__.py
54+
```
55+
56+
- Create a new file `database.py` and copy in the following code.
57+
- In your SQLite Cloud account dashboard, click on `Show connection strings`, copy the Connection String, and replace `<your-connection-string>` below. Modify your string to include the name of the DB we'll query: `sqlitecloud://{hostname}:8860/chinook.sqlite?apikey={apikey}`.
58+
59+
```py
60+
from sqlalchemy import create_engine
61+
from sqlalchemy.orm import sessionmaker
62+
from sqlalchemy.ext.declarative import declarative_base
63+
64+
engine = create_engine('<your-connection-string>')
65+
66+
SessionLocal = sessionmaker(bind=engine)
67+
68+
Base = declarative_base()
69+
```
70+
71+
- Create a new file `models.py` and copy in the following code defining 2 SQLAlchemy ORM "models", or classes, to interact with the DB.
72+
- `__tablename__` is the name of a model's corresponding DB table.
73+
- The `Album` class' `id` attribute maps to the `AlbumId` column in the `albums` table. All other class attribute names match their corresponding table column names.
74+
75+
```py
76+
from .database import Base
77+
78+
from sqlalchemy import Column, ForeignKey, Integer, String
79+
80+
class Artist(Base):
81+
__tablename__ = "artists"
82+
83+
ArtistId = Column(Integer, primary_key=True)
84+
Name = Column(String)
85+
86+
class Album(Base):
87+
__tablename__ = "albums"
88+
89+
id = Column("AlbumId", Integer, primary_key=True)
90+
Title = Column(String)
91+
ArtistId = Column(Integer, ForeignKey('artists.ArtistId'))
92+
```
93+
94+
- Create a new file `schemas.py` and copy in the following code defining a Pydantic model, or "schema", to validate the shape of the response data.
95+
96+
```py
97+
from pydantic import BaseModel
98+
99+
class AlbumResponse(BaseModel):
100+
id: int
101+
Title: str
102+
ArtistName: str
103+
```
104+
105+
- Create a new file `read.py` and copy in the following code creating a reusable utility function to read album data.
106+
107+
```py
108+
from . import models
109+
110+
from sqlalchemy.orm import Session
111+
112+
def get_albums(db: Session, skip: int = 0, num: int = 20):
113+
return db.query(models.Album.id, models.Album.Title, models.Artist.Name.label('ArtistName')).join(models.Artist).offset(skip).limit(num).all()
114+
```
115+
116+
- Create a new file `main.py` and copy in the following code.
117+
- The `get_db` function handles creating and closing a new `SessionLocal` instance, or DB connection/ session, for every request.
118+
- A GET request to the `/albums/` endpoint calls the `read_albums` function, which returns a list of SQLAlchemy `Album` models. The `response_model` ensures only data declared in the Pydantic schema is returned to the client.
119+
- The `AlbumResponse` Pydantic model in `schemas.py` has `ArtistName`, as opposed to `ArtistId` defined in the `Album` SQLAlchemy model in `models.py`.
120+
- `read_albums` calls the `get_albums` function in `read.py`. `get_albums` queries the `Album` ORM model/ `albums` DB table for the first 20 albums, and joins the `Artist` ORM model/ `artists` DB table to retrieve the `Artist.Name` (re-labeled `ArtistName`) expected by the `AlbumResponse` Pydantic model.
121+
122+
```py
123+
from .database import SessionLocal
124+
from . import read, schemas
125+
126+
from fastapi import FastAPI, Depends
127+
from sqlalchemy.orm import Session
128+
129+
app = FastAPI()
130+
131+
def get_db():
132+
db = SessionLocal()
133+
try:
134+
yield db
135+
finally:
136+
db.close()
137+
138+
@app.get("/albums/", response_model=list[schemas.AlbumResponse])
139+
def read_albums(skip: int = 0, num: int = 20, db: Session = Depends(get_db)):
140+
albums = read.get_albums(db, skip=skip, num=num)
141+
return albums
142+
```
143+
144+
5. **Run your FastAPI app**
145+
- From your `sqlalchemy-quickstart` directory, run the following command:
146+
147+
```bash
148+
uvicorn fastapi_sqlc_app.main:app --reload
149+
```
150+
151+
- Visit `http://127.0.0.1:8000/albums/` to see your app data.
152+
153+
6. **Troubleshooting**
154+
155+
- If you encounter the following error, restart your IDE and re-run your app.
156+
157+
```bash
158+
AttributeError: module 'sqlitecloud.dbapi2' has no attribute 'sqlite_version_info'`
159+
```
160+
161+
7. **References**
162+
163+
- [FastAPI introductory example](https://fastapi.tiangolo.com/#example)
164+
- [FastAPI SQL Databases tutorial](https://fastapi.tiangolo.com/tutorial/sql-databases/)
165+
- [Latest SQLAlchemy docs](https://docs.sqlalchemy.org/en/20/)
166+
167+
And that's it! You've successfully built a FastAPI app that uses SQLAlchemy ORM to read data from a SQLite Cloud database.

sqlite-cloud/reference/backup-commands.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ slug: backup-commands
77
---
88

99
## APPLY BACKUP SETTINGS
10-
Several backup-related settings can be applied using the SET DATABASE KEY command.
10+
Several backup-related settings can be applied using the [SET DATABASE KEY](https://docs.sqlitecloud.io/docs/settings-commands#set-database-key) command.
1111

1212
The following keys affect the backup settings:
1313
* **backup**: set to 1 to activate a backup, 0 to disable.

sqlite-cloud/sdks/python/introduction.mdx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ dfprices = pd.read_csv(
5757
)
5858
)
5959

60+
# Your SQLite Cloud connection string
6061
conn = sqlitecloud.connect("sqlitecloud://myhost.sqlite.cloud:8860/mydatabase.sqlite?apikey=myapikey")
6162

6263
conn.executemany("DROP TABLE IF EXISTS ?", [("PRICES",)])
@@ -76,3 +77,61 @@ query_result = df_actual_prices.query("PRICE > 50.00")
7677
print(query_result)
7778
```
7879

80+
## Using SQLite Cloud with SQLAlchemy
81+
82+
```bash
83+
pip install sqlalchemy-sqlitecloud
84+
```
85+
86+
```python
87+
import sqlalchemy
88+
from sqlalchemy import Column, ForeignKey, Integer, String
89+
from sqlalchemy.dialects import registry
90+
from sqlalchemy.orm import backref, declarative_base, relationship, sessionmaker
91+
92+
Base = declarative_base()
93+
94+
95+
class Artist(Base):
96+
__tablename__ = "artists"
97+
98+
ArtistId = Column("ArtistId", Integer, primary_key=True)
99+
Name = Column("Name", String)
100+
Albums = relationship("Album", backref=backref("artist"))
101+
102+
103+
class Album(Base):
104+
__tablename__ = "albums"
105+
106+
AlbumId = Column("AlbumId", Integer, primary_key=True)
107+
ArtistId = Column("ArtistId", Integer, ForeignKey("artists.ArtistId"))
108+
Title = Column("Title", String)
109+
110+
# Your SQLite Cloud connection string
111+
connection_string = "sqlitecloud://myhost.sqlite.cloud:8860/mydatabase.sqlite?apikey=myapikey"
112+
113+
engine = sqlalchemy.create_engine(connection_string)
114+
Session = sessionmaker(bind=engine)
115+
session = Session()
116+
117+
name = "John Doe"
118+
query = sqlalchemy.insert(Artist).values(Name=name)
119+
result_insert = session.execute(query)
120+
121+
title = "The Album"
122+
query = sqlalchemy.insert(Album).values(
123+
ArtistId=result_insert.lastrowid, Title=title
124+
)
125+
session.execute(query)
126+
127+
query = (
128+
sqlalchemy.select(Artist, Album)
129+
.join(Album, Artist.ArtistId == Album.ArtistId)
130+
.where(Artist.ArtistId == result_insert.lastrowid)
131+
)
132+
133+
result = session.execute(query).fetchone()
134+
135+
print("Artist Name: " + result[0].Name)
136+
print("Album Title: " + result[1].Title)
137+
```

0 commit comments

Comments
 (0)