Skip to content
This repository was archived by the owner on Jun 5, 2025. It is now read-only.

Commit f871716

Browse files
Luke Hindsaponcedeleonch
authored andcommitted
Database schema and sqlc configs
Map out what a database could look like to serve the frontend. I went with SQLC , good balance of safety and speed, coupled with SQLite is an embedded database, meaning no extra service to run in the singular container
1 parent 1179eb4 commit f871716

File tree

13 files changed

+1214
-12
lines changed

13 files changed

+1214
-12
lines changed

codegate.db

60 KB
Binary file not shown.

poetry.lock

Lines changed: 196 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ transformers = ">=4.46.3"
1919
structlog = ">=24.4.0"
2020
litellm = "^1.52.16"
2121
llama_cpp_python = ">=0.3.2"
22-
2322
cryptography = "^44.0.0"
23+
sqlalchemy = "^2.0.28"
24+
greenlet = "^3.0.3"
25+
aiosqlite = "^0.19.0"
26+
2427
[tool.poetry.group.dev.dependencies]
2528
pytest = ">=7.4.0"
2629
pytest-cov = ">=4.1.0"

sql/queries/queries.sql

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
-- name: CreatePrompt :one
2+
INSERT INTO prompts (
3+
id,
4+
timestamp,
5+
provider,
6+
system_prompt,
7+
user_prompt,
8+
type,
9+
status
10+
) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING *;
11+
12+
-- name: GetPrompt :one
13+
SELECT * FROM prompts WHERE id = ?;
14+
15+
-- name: ListPrompts :many
16+
SELECT * FROM prompts
17+
ORDER BY timestamp DESC
18+
LIMIT ? OFFSET ?;
19+
20+
-- name: CreateOutput :one
21+
INSERT INTO outputs (
22+
id,
23+
prompt_id,
24+
timestamp,
25+
output,
26+
status
27+
) VALUES (?, ?, ?, ?, ?) RETURNING *;
28+
29+
-- name: GetOutput :one
30+
SELECT * FROM outputs WHERE id = ?;
31+
32+
-- name: GetOutputsByPromptId :many
33+
SELECT * FROM outputs
34+
WHERE prompt_id = ?
35+
ORDER BY timestamp DESC;
36+
37+
-- name: CreateAlert :one
38+
INSERT INTO alerts (
39+
id,
40+
prompt_id,
41+
output_id,
42+
code_snippet,
43+
trigger_string,
44+
trigger_type,
45+
trigger_category,
46+
timestamp
47+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?) RETURNING *;
48+
49+
-- name: GetAlert :one
50+
SELECT * FROM alerts WHERE id = ?;
51+
52+
-- name: ListAlertsByPrompt :many
53+
SELECT * FROM alerts
54+
WHERE prompt_id = ?
55+
ORDER BY timestamp DESC;
56+
57+
-- name: GetSettings :one
58+
SELECT * FROM settings ORDER BY id LIMIT 1;
59+
60+
-- name: UpsertSettings :one
61+
INSERT INTO settings (
62+
id,
63+
ip,
64+
port,
65+
llm_model,
66+
system_prompt,
67+
other_settings
68+
) VALUES (?, ?, ?, ?, ?, ?)
69+
ON CONFLICT(id) DO UPDATE SET
70+
ip = excluded.ip,
71+
port = excluded.port,
72+
llm_model = excluded.llm_model,
73+
system_prompt = excluded.system_prompt,
74+
other_settings = excluded.other_settings
75+
RETURNING *;
76+
77+
-- name: GetPromptWithOutputsAndAlerts :many
78+
SELECT
79+
p.*,
80+
o.id as output_id,
81+
o.output,
82+
o.status as output_status,
83+
a.id as alert_id,
84+
a.code_snippet,
85+
a.trigger_string,
86+
a.trigger_type,
87+
a.trigger_category
88+
FROM prompts p
89+
LEFT JOIN outputs o ON p.id = o.prompt_id
90+
LEFT JOIN alerts a ON p.id = a.prompt_id
91+
WHERE p.id = ?
92+
ORDER BY o.timestamp DESC, a.timestamp DESC;

sql/schema/schema.sql

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
-- Schema for codegate database using SQLite
2+
3+
-- Prompts table
4+
CREATE TABLE prompts (
5+
id TEXT PRIMARY KEY, -- UUID stored as TEXT
6+
timestamp DATETIME NOT NULL,
7+
provider TEXT, -- VARCHAR(255)
8+
system_prompt TEXT,
9+
user_prompt TEXT NOT NULL,
10+
type TEXT NOT NULL, -- VARCHAR(50) (e.g. "fim", "chat")
11+
status TEXT NOT NULL -- VARCHAR(50)
12+
);
13+
14+
-- Outputs table
15+
CREATE TABLE outputs (
16+
id TEXT PRIMARY KEY, -- UUID stored as TEXT
17+
prompt_id TEXT NOT NULL,
18+
timestamp DATETIME NOT NULL,
19+
output TEXT NOT NULL,
20+
status TEXT NOT NULL, -- VARCHAR(50)
21+
FOREIGN KEY (prompt_id) REFERENCES prompts(id)
22+
);
23+
24+
-- Alerts table
25+
CREATE TABLE alerts (
26+
id TEXT PRIMARY KEY, -- UUID stored as TEXT
27+
prompt_id TEXT NOT NULL,
28+
output_id TEXT NOT NULL,
29+
code_snippet TEXT NOT NULL, -- VARCHAR(255)
30+
trigger_string TEXT NOT NULL, -- VARCHAR(255)
31+
trigger_type TEXT NOT NULL, -- VARCHAR(50)
32+
trigger_category TEXT,
33+
timestamp DATETIME NOT NULL,
34+
FOREIGN KEY (prompt_id) REFERENCES prompts(id),
35+
FOREIGN KEY (output_id) REFERENCES outputs(id)
36+
);
37+
38+
-- Settings table
39+
CREATE TABLE settings (
40+
id TEXT PRIMARY KEY, -- UUID stored as TEXT
41+
ip TEXT, -- VARCHAR(45)
42+
port INTEGER,
43+
llm_model TEXT, -- VARCHAR(255)
44+
system_prompt TEXT,
45+
other_settings TEXT -- JSON stored as TEXT
46+
);
47+
48+
-- Create indexes for foreign keys and frequently queried columns
49+
CREATE INDEX idx_outputs_prompt_id ON outputs(prompt_id);
50+
CREATE INDEX idx_alerts_prompt_id ON alerts(prompt_id);
51+
CREATE INDEX idx_alerts_output_id ON alerts(output_id);
52+
CREATE INDEX idx_prompts_timestamp ON prompts(timestamp);
53+
CREATE INDEX idx_outputs_timestamp ON outputs(timestamp);
54+
CREATE INDEX idx_alerts_timestamp ON alerts(timestamp);

sqlc.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
version: "2"
2+
plugins:
3+
- name: "python"
4+
wasm:
5+
url: "https://downloads.sqlc.dev/plugin/sqlc-gen-python_1.2.0.wasm"
6+
sha256: "a6c5d174c407007c3717eea36ff0882744346e6ba991f92f71d6ab2895204c0e"
7+
8+
sql:
9+
- engine: "sqlite"
10+
schema: "sql/schema"
11+
queries: "sql/queries"
12+
codegen:
13+
- plugin: "python"
14+
out: "src/codegate/db"
15+
options:
16+
package: "codegate.db"
17+
emit_sync_querier: true
18+
emit_async_querier: true
19+
query_parameter_limit: 5

src/codegate/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from codegate.codegate_logging import LogFormat, LogLevel, setup_logging
1111
from codegate.config import Config, ConfigurationError
12-
from codegate.server import init_app
12+
from codegate.server import create_app
1313

1414

1515
def validate_port(ctx: click.Context, param: click.Parameter, value: int) -> int:
@@ -164,7 +164,7 @@ def serve(
164164
},
165165
)
166166

167-
app = init_app()
167+
app = create_app()
168168

169169
import uvicorn
170170

src/codegate/db/init_db.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import asyncio
2+
from pathlib import Path
3+
4+
from sqlalchemy import text
5+
from sqlalchemy.ext.asyncio import create_async_engine
6+
7+
8+
async def init_db():
9+
"""Initialize the database with the schema."""
10+
# Get the absolute path to the schema file
11+
current_dir = Path(__file__).parent
12+
schema_path = current_dir.parent.parent.parent / "sql" / "schema" / "schema.sql"
13+
14+
if not schema_path.exists():
15+
raise FileNotFoundError(f"Schema file not found at {schema_path}")
16+
17+
# Read the schema
18+
with open(schema_path, "r") as f:
19+
schema = f.read()
20+
21+
# Create the database engine with proper async SQLite URL
22+
db_path = Path("codegate.db").absolute()
23+
engine = create_async_engine(
24+
f"sqlite+aiosqlite:///{db_path}",
25+
echo=True, # Set to False in production
26+
isolation_level="AUTOCOMMIT", # Required for SQLite
27+
)
28+
29+
try:
30+
# Execute the schema
31+
async with engine.begin() as conn:
32+
# Split the schema into individual statements and execute each one
33+
statements = [stmt.strip() for stmt in schema.split(";") if stmt.strip()]
34+
for statement in statements:
35+
# Use SQLAlchemy text() to create executable SQL statements
36+
await conn.execute(text(statement))
37+
finally:
38+
await engine.dispose()
39+
40+
41+
def init_db_sync():
42+
"""Synchronous wrapper for init_db."""
43+
asyncio.run(init_db())
44+
45+
46+
if __name__ == "__main__":
47+
init_db_sync()

src/codegate/db/models.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Code generated by sqlc. DO NOT EDIT.
2+
# versions:
3+
# sqlc v1.27.0
4+
import dataclasses
5+
from typing import Any, Optional
6+
7+
8+
@dataclasses.dataclass()
9+
class Alert:
10+
id: Any
11+
prompt_id: Any
12+
output_id: Any
13+
code_snippet: Any
14+
trigger_string: Any
15+
trigger_type: Any
16+
trigger_category: Optional[Any]
17+
timestamp: Any
18+
19+
20+
@dataclasses.dataclass()
21+
class Output:
22+
id: Any
23+
prompt_id: Any
24+
timestamp: Any
25+
output: Any
26+
status: Any
27+
28+
29+
@dataclasses.dataclass()
30+
class Prompt:
31+
id: Any
32+
timestamp: Any
33+
provider: Optional[Any]
34+
system_prompt: Optional[Any]
35+
user_prompt: Any
36+
type: Any
37+
status: Any
38+
39+
40+
@dataclasses.dataclass()
41+
class Setting:
42+
id: Any
43+
ip: Optional[Any]
44+
port: Optional[Any]
45+
llm_model: Optional[Any]
46+
system_prompt: Optional[Any]
47+
other_settings: Optional[Any]

0 commit comments

Comments
 (0)