initial commit
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
def sql_literal(value: object) -> str:
|
||||
if value is None:
|
||||
return "NULL"
|
||||
if isinstance(value, bool):
|
||||
return "TRUE" if value else "FALSE"
|
||||
text = str(value)
|
||||
return "'" + text.replace("'", "''") + "'"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Database:
|
||||
url: str
|
||||
|
||||
def execute(self, sql: str) -> None:
|
||||
subprocess.run(
|
||||
["psql", self.url, "-X", "-v", "ON_ERROR_STOP=1", "-q"],
|
||||
input=sql,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
def rows(self, sql: str) -> list[dict[str, str | None]]:
|
||||
result = subprocess.run(
|
||||
[
|
||||
"psql",
|
||||
self.url,
|
||||
"-X",
|
||||
"-v",
|
||||
"ON_ERROR_STOP=1",
|
||||
"-q",
|
||||
"-P",
|
||||
"footer=off",
|
||||
"-A",
|
||||
"-F",
|
||||
"\t",
|
||||
"-c",
|
||||
sql,
|
||||
],
|
||||
text=True,
|
||||
check=True,
|
||||
capture_output=True,
|
||||
)
|
||||
lines = [line for line in result.stdout.splitlines() if line.strip()]
|
||||
if not lines:
|
||||
return []
|
||||
headers = lines[0].split("\t")
|
||||
out: list[dict[str, str | None]] = []
|
||||
for line in lines[1:]:
|
||||
values = line.split("\t")
|
||||
out.append(
|
||||
{
|
||||
key: None if idx >= len(values) or values[idx] == "" else values[idx]
|
||||
for idx, key in enumerate(headers)
|
||||
}
|
||||
)
|
||||
return out
|
||||
|
||||
def one(self, sql: str) -> dict[str, str | None] | None:
|
||||
rows = self.rows(sql)
|
||||
return rows[0] if rows else None
|
||||
|
||||
Reference in New Issue
Block a user