Skip to content

Commit 3a2b877

Browse files
authored
feat(sqlite3) Added sqlite3 driver (#17)
* chore: update sqlc-gen-better-python version to v0.0.1 (feature/sqlite3) * feat(sqlite3): Add SQLite3 driver for Python code generation (feature/sqlite3) * refactor(sqlc-gen): prefix AioSQLite functions (feature/sqlite3) * feat(sqlc.yaml): Update wasm sha256 and change sql driver to sqlite3 (#feature/sqlite3) * feat(sqlite3): Added support for driver `sqlite3` (PR: 17)
1 parent a0cc6a7 commit 3a2b877

8 files changed

Lines changed: 172 additions & 45 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Added
2+
body: Added support for driver `sqlite3`
3+
time: 2025-04-01T01:31:09.0893687+02:00
4+
custom:
5+
Author: rayakame
6+
PR: "17"

internal/codegen/common.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@ func NewDriver(conf *core.Config) (*Driver, error) {
2626
var connType string
2727
switch conf.SqlDriver {
2828
case core.SQLDriverAioSQLite:
29-
buildPyQueryFunc = drivers.BuildPyQueryFunc
30-
acceptedDriverCMDs = drivers.AcceptedDriverCMDs
29+
buildPyQueryFunc = drivers.AioSQLiteBuildPyQueryFunc
30+
acceptedDriverCMDs = drivers.AioSQLiteAcceptedDriverCMDs
3131
connType = drivers.AioSQLiteConn
32-
32+
case core.SQLDriverSQLite:
33+
buildPyQueryFunc = drivers.SQLite3BuildPyQueryFunc
34+
acceptedDriverCMDs = drivers.SQLite3AcceptedDriverCMDs
35+
connType = drivers.SQLite3Conn
3336
default:
3437
return nil, fmt.Errorf("unsupported driver: %s", conf.SqlDriver.String())
3538
}

internal/codegen/drivers/aiosqlite.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
const AioSQLiteConn = "aiosqlite.Connection"
1212

13-
func BuildPyQueryFunc(query *core.Query, body *builders.IndentStringBuilder, argType string, retType string, isClass bool) error {
13+
func AioSQLiteBuildPyQueryFunc(query *core.Query, body *builders.IndentStringBuilder, argType string, retType string, isClass bool) error {
1414
indentLevel := 0
1515
params := fmt.Sprintf("conn: %s", AioSQLiteConn)
1616
conn := "conn"
@@ -132,7 +132,7 @@ func BuildPyQueryFunc(query *core.Query, body *builders.IndentStringBuilder, arg
132132
return nil
133133
}
134134

135-
func AcceptedDriverCMDs() []string {
135+
func AioSQLiteAcceptedDriverCMDs() []string {
136136
return []string{
137137
metadata.CmdExec,
138138
metadata.CmdExecResult,
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package drivers
2+
3+
import (
4+
"fmt"
5+
"github.com/rayakame/sqlc-gen-better-python/internal/codegen/builders"
6+
"github.com/rayakame/sqlc-gen-better-python/internal/core"
7+
"github.com/sqlc-dev/plugin-sdk-go/metadata"
8+
"strconv"
9+
)
10+
11+
const SQLite3Conn = "sqlite3.Connection"
12+
13+
func SQLite3BuildPyQueryFunc(query *core.Query, body *builders.IndentStringBuilder, argType string, retType string, isClass bool) error {
14+
indentLevel := 0
15+
params := fmt.Sprintf("conn: %s", SQLite3Conn)
16+
conn := "conn"
17+
if isClass {
18+
params = "self"
19+
conn = "self._conn"
20+
indentLevel = 1
21+
}
22+
body.WriteIndentedString(indentLevel, fmt.Sprintf("def %s(%s", query.FuncName, params))
23+
if argType != "" {
24+
body.WriteString(fmt.Sprintf(", %s: %s", query.Arg.Name, argType))
25+
}
26+
if query.Cmd == metadata.CmdExec {
27+
body.WriteLine(fmt.Sprintf(") -> %s:", retType))
28+
body.WriteIndentedString(indentLevel+1, fmt.Sprintf("%s.execute(%s", conn, query.ConstantName))
29+
writeParams(query, body, argType)
30+
body.WriteLine(")")
31+
} else if query.Cmd == metadata.CmdExecResult {
32+
body.WriteLine(fmt.Sprintf(") -> %s:", "sqlite3.Cursor"))
33+
body.WriteIndentedString(indentLevel+1, fmt.Sprintf("%s.execute(%s", conn, query.ConstantName))
34+
writeParams(query, body, argType)
35+
body.WriteLine(")")
36+
} else if query.Cmd == metadata.CmdExecRows {
37+
body.WriteLine(fmt.Sprintf(") -> %s:", retType))
38+
body.WriteIndentedString(indentLevel+1, fmt.Sprintf("%s.execute(%s", conn, query.ConstantName))
39+
writeParams(query, body, argType)
40+
body.WriteLine(").rowcount")
41+
} else if query.Cmd == metadata.CmdExecLastId {
42+
body.WriteLine(fmt.Sprintf(") -> %s:", retType))
43+
body.WriteIndentedString(indentLevel+1, fmt.Sprintf("%s.execute(%s", conn, query.ConstantName))
44+
writeParams(query, body, argType)
45+
body.WriteLine(").lastrowid")
46+
} else if query.Cmd == metadata.CmdOne {
47+
body.WriteLine(fmt.Sprintf(") -> typing.Optional[%s]:", retType))
48+
body.WriteIndentedString(indentLevel+1, fmt.Sprintf("row = %s.execute(%s", conn, query.ConstantName))
49+
writeParams(query, body, argType)
50+
body.WriteLine(").fetchone()")
51+
body.WriteIndentedLine(indentLevel+1, "if row is None:")
52+
body.WriteIndentedLine(indentLevel+2, "return None")
53+
if query.Ret.IsStruct() {
54+
body.WriteIndentedString(indentLevel+1, fmt.Sprintf("return %s(", retType))
55+
for i, col := range query.Ret.Table.Columns {
56+
if i != 0 {
57+
body.WriteString(", ")
58+
}
59+
body.WriteString(fmt.Sprintf("%s=row[%s]", col.Name, strconv.Itoa(i)))
60+
}
61+
body.WriteLine(")")
62+
} else {
63+
body.WriteIndentedLine(indentLevel+1, fmt.Sprintf("return %s(row[0])", retType))
64+
}
65+
} else if query.Cmd == metadata.CmdMany {
66+
body.WriteLine(fmt.Sprintf(") -> typing.List[%s]:", retType))
67+
body.WriteIndentedLine(indentLevel+1, fmt.Sprintf("rows: typing.List[%s] = []", retType))
68+
body.WriteIndentedString(indentLevel+1, fmt.Sprintf("for row in %s.execute(%s", conn, query.ConstantName))
69+
writeParams(query, body, argType)
70+
body.WriteLine(").fetchall():")
71+
if query.Ret.IsStruct() {
72+
body.WriteIndentedString(indentLevel+2, fmt.Sprintf("rows.append(%s(", retType))
73+
for i, col := range query.Ret.Table.Columns {
74+
if i != 0 {
75+
body.WriteString(", ")
76+
}
77+
body.WriteString(fmt.Sprintf("%s=row[%s]", col.Name, strconv.Itoa(i)))
78+
}
79+
body.WriteLine("))")
80+
} else {
81+
body.WriteIndentedLine(indentLevel+2, fmt.Sprintf("rows.append(%s(row[0]))", retType))
82+
}
83+
body.WriteIndentedLine(indentLevel+1, "return rows")
84+
}
85+
return nil
86+
}
87+
88+
func SQLite3AcceptedDriverCMDs() []string {
89+
return []string{
90+
metadata.CmdExec,
91+
metadata.CmdExecResult,
92+
metadata.CmdExecLastId,
93+
metadata.CmdExecRows,
94+
metadata.CmdOne,
95+
metadata.CmdMany,
96+
}
97+
}
98+
99+
func writeParams(query *core.Query, body *builders.IndentStringBuilder, argType string) {
100+
if argType != "" {
101+
params := "("
102+
if query.Arg.IsStruct() {
103+
for _, col := range query.Arg.Table.Columns {
104+
params += fmt.Sprintf("%s.%s, ", query.Arg.Name, col.Name)
105+
}
106+
} else {
107+
params += fmt.Sprintf("%s, ", query.Arg.Name)
108+
}
109+
body.WriteString("," + params + ")")
110+
}
111+
}

sqlc.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ plugins:
33
- name: python
44
wasm:
55
url: file://sqlc-gen-better-python.wasm
6-
sha256: 67389a6e3bfdaf7e78ff7e85a4c497beb849aff7de9d4e283feda44ffe3f22a3
6+
sha256: be2dfe3e1b9afa91b81212ed983fc1e2b507c58c6ed9c757e902756dd1de1de9
77
sql:
88
- schema: test/schema.sql
99
queries: test/queries.sql
@@ -13,7 +13,7 @@ sql:
1313
plugin: python
1414
options:
1515
package: test
16-
sql_driver: aiosqlite
16+
sql_driver: sqlite3
1717
model_type: dataclass
18-
emit_classes: true
18+
emit_classes: false
1919

test/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Code generated by sqlc. DO NOT EDIT.
22
# versions:
33
# sqlc v1.28.0
4-
# sqlc-gen-better-python 0.0.1
4+
# sqlc-gen-better-python v0.0.1

test/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Code generated by sqlc. DO NOT EDIT.
22
# versions:
33
# sqlc v1.28.0
4-
# sqlc-gen-better-python 0.0.1
4+
# sqlc-gen-better-python v0.0.1
55
from __future__ import annotations
66

77
__all__: typing.Sequence[str] = (

test/queries.py

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
# Code generated by sqlc. DO NOT EDIT.
22
# versions:
33
# sqlc v1.28.0
4-
# sqlc-gen-better-python 0.0.1
4+
# sqlc-gen-better-python v0.0.1
55
from __future__ import annotations
66

77
__all__: typing.Sequence[str] = (
88
"CreateAuthorParams",
99
"GetAuthorRow",
10-
"Queries",
1110
"UpdateAuthorParams",
1211
"UpdateAuthorTParams",
1312
"UpsertAuthorNameParams",
13+
"create_author",
14+
"delete_author",
15+
"get_author",
16+
"list_authors",
17+
"update_author",
18+
"update_author_t",
19+
"upsert_author_name",
1420
)
1521

1622
import dataclasses
1723
import typing
1824

19-
import aiosqlite
25+
import sqlite3
2026

2127
from test import models
2228

@@ -101,43 +107,44 @@ class UpsertAuthorNameParams:
101107
"""
102108

103109

104-
class Queries:
105-
__slots__ = ("_conn",)
110+
def create_author(conn: sqlite3.Connection, arg: CreateAuthorParams) -> typing.Optional[models.Author]:
111+
row = conn.execute(CREATE_AUTHOR,(arg.name, arg.bio, )).fetchone()
112+
if row is None:
113+
return None
114+
return models.Author(id=row[0], name=row[1], bio=row[2])
106115

107-
def __init__(self, conn: aiosqlite.Connection):
108-
self._conn = conn
109116

110-
async def create_author(self, arg: CreateAuthorParams) -> typing.Optional[models.Author]:
111-
row = await (await self._conn.execute(CREATE_AUTHOR, arg.name, arg.bio)).fetchone()
112-
if row is None:
113-
return None
114-
return models.Author(id=row[0], name=row[1], bio=row[2])
117+
def delete_author(conn: sqlite3.Connection, id: int) -> None:
118+
conn.execute(DELETE_AUTHOR,(id, ))
115119

116-
async def delete_author(self, id: int) -> None:
117-
await self._conn.execute(DELETE_AUTHOR, id)
118120

119-
async def get_author(self, id: int) -> typing.Optional[GetAuthorRow]:
120-
row = await (await self._conn.execute(GET_AUTHOR, id)).fetchone()
121-
if row is None:
122-
return None
123-
return GetAuthorRow(id=row[0], name=row[1])
121+
def get_author(conn: sqlite3.Connection, id: int) -> typing.Optional[GetAuthorRow]:
122+
row = conn.execute(GET_AUTHOR,(id, )).fetchone()
123+
if row is None:
124+
return None
125+
return GetAuthorRow(id=row[0], name=row[1])
124126

125-
async def list_authors(self, ids: typing.Sequence[int]) -> typing.AsyncIterator[models.Author]:
126-
stream = await self._conn.execute(LIST_AUTHORS, ids)
127-
async for row in stream:
128-
yield models.Author(id=row[0], name=row[1], bio=row[2])
129127

130-
async def update_author(self, arg: UpdateAuthorParams) -> None:
131-
await self._conn.execute(UPDATE_AUTHOR, arg.name, arg.bio, arg.id)
128+
def list_authors(conn: sqlite3.Connection, ids: typing.Sequence[int]) -> typing.List[models.Author]:
129+
rows: typing.List[models.Author] = []
130+
for row in conn.execute(LIST_AUTHORS,(ids, )).fetchall():
131+
rows.append(models.Author(id=row[0], name=row[1], bio=row[2]))
132+
return rows
132133

133-
async def update_author_t(self, arg: UpdateAuthorTParams) -> typing.Optional[models.Author]:
134-
row = await (await self._conn.execute(UPDATE_AUTHOR_T, arg.name, arg.bio, arg.id)).fetchone()
135-
if row is None:
136-
return None
137-
return models.Author(id=row[0], name=row[1], bio=row[2])
138134

139-
async def upsert_author_name(self, arg: UpsertAuthorNameParams) -> typing.Optional[models.Author]:
140-
row = await (await self._conn.execute(UPSERT_AUTHOR_NAME, arg.set_name, arg.name)).fetchone()
141-
if row is None:
142-
return None
143-
return models.Author(id=row[0], name=row[1], bio=row[2])
135+
def update_author(conn: sqlite3.Connection, arg: UpdateAuthorParams) -> None:
136+
conn.execute(UPDATE_AUTHOR,(arg.name, arg.bio, arg.id, ))
137+
138+
139+
def update_author_t(conn: sqlite3.Connection, arg: UpdateAuthorTParams) -> typing.Optional[models.Author]:
140+
row = conn.execute(UPDATE_AUTHOR_T,(arg.name, arg.bio, arg.id, )).fetchone()
141+
if row is None:
142+
return None
143+
return models.Author(id=row[0], name=row[1], bio=row[2])
144+
145+
146+
def upsert_author_name(conn: sqlite3.Connection, arg: UpsertAuthorNameParams) -> typing.Optional[models.Author]:
147+
row = conn.execute(UPSERT_AUTHOR_NAME,(arg.set_name, arg.name, )).fetchone()
148+
if row is None:
149+
return None
150+
return models.Author(id=row[0], name=row[1], bio=row[2])

0 commit comments

Comments
 (0)