Initial commit: local SQL expert AI (Ollama + CLI + prompts + systemd timer)
This commit is contained in:
11
.env.example
Normal file
11
.env.example
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Base model to pull and use for the expert model
|
||||||
|
BASE_MODEL=qwen2.5-coder:14b
|
||||||
|
|
||||||
|
# Optional: space-separated list of extra models to pull
|
||||||
|
EXTRA_MODELS=sqlcoder
|
||||||
|
|
||||||
|
# Name of your custom expert model (built from Modelfile)
|
||||||
|
EXPERT_MODEL=jr-sql-expert
|
||||||
|
|
||||||
|
# Ollama API endpoint (host network)
|
||||||
|
OLLAMA_URL=http://127.0.0.1:11434
|
||||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
logs/*.log
|
||||||
|
.env
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
31
Modelfile
Normal file
31
Modelfile
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# NOTE: scripts will replace ${BASE_MODEL} with your .env BASE_MODEL.
|
||||||
|
FROM ${BASE_MODEL}
|
||||||
|
|
||||||
|
SYSTEM """
|
||||||
|
Du bist ein sehr erfahrener Microsoft SQL Server 2022 Engineer (T-SQL, Query Optimizer, Indexing, Execution Plans, Stored Procedures, Views, Schema-Design, Collations/UTF-8).
|
||||||
|
Du arbeitest offline und machst KEINE Annahmen über reale Daten. Keine Verbindungen, keine Ausführung – nur Analyse.
|
||||||
|
|
||||||
|
Allgemeine Regeln:
|
||||||
|
- Antworte präzise, technisch, ohne Marketing.
|
||||||
|
- Wenn Informationen fehlen: liste exakt auf, was fehlt, und gib trotzdem best-effort Analyse.
|
||||||
|
- Wenn du Snippets vorschlägst: immer konkret (T-SQL/DDL) und kommentiert.
|
||||||
|
- Wenn du mehrere Optionen gibst: nenne Vor-/Nachteile und wann welche Option sinnvoll ist.
|
||||||
|
|
||||||
|
Für Query Plans:
|
||||||
|
- Erkläre Hotspots (Top Operatoren), Kardinalitätsschätzungen, Warnungen, Spills, SARGability,
|
||||||
|
fehlende Indizes (vorsichtig!), Join-Strategien, Parameter Sniffing, Stats, Memory Grants.
|
||||||
|
|
||||||
|
Für UTF-8 Migration:
|
||||||
|
- Erkläre Vorgehen über UTF-8-enabled Collations (_UTF8).
|
||||||
|
- Risiken: Vergleiche/Sortierung, Indexgrößen, Abhängigkeiten (FK/Index/Computed/Triggers),
|
||||||
|
Teststrategie, Cutover, Rollback.
|
||||||
|
|
||||||
|
Antwort-Struktur (immer):
|
||||||
|
1) Kurzfazit (3–6 Bulletpoints)
|
||||||
|
2) Detailanalyse (mit konkreten Snippets)
|
||||||
|
3) Risiken & Checks (Checkliste)
|
||||||
|
4) Nächste Schritte
|
||||||
|
"""
|
||||||
|
|
||||||
|
PARAMETER temperature 0.1
|
||||||
|
PARAMETER top_p 0.9
|
||||||
84
README.md
Normal file
84
README.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# jr-sql-ai (Terminal-first SQL Server Expert KI, lokal)
|
||||||
|
|
||||||
|
Ziel: Lokale Expert-KI für **SQL Server 2022** (T-SQL, Views, Stored Procedures, Execution Plans, UTF-8 Migration),
|
||||||
|
aufrufbar **vom Terminal**, ohne direkte DB-Verbindung (nur Copy & Paste / Dateien).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- **Einfacher Tech-Stack:** Docker + Ollama + Bash + curl + python
|
||||||
|
- **Host Networking:** nutzt den Host-Netzwerkstack (Routing/DNS wie Host; ideal wenn nur `br0` zuverlässig ist)
|
||||||
|
- **Auto-Updates:** Runtime + Models via `systemd --user` Timer
|
||||||
|
- **Viele Logs:** jede Ausführung schreibt detaillierte Logs unter `./logs/`
|
||||||
|
|
||||||
|
## Voraussetzungen (Arch Linux)
|
||||||
|
- docker + docker compose
|
||||||
|
- curl
|
||||||
|
- python (für JSON-Quoting/Parsing)
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
./scripts/bootstrap.sh
|
||||||
|
echo "SELECT 1;" | ./bin/sqlai analyze-tsql
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verwendung (Copy & Paste)
|
||||||
|
### T-SQL
|
||||||
|
```bash
|
||||||
|
cat query.sql | ./bin/sqlai analyze-tsql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stored Procedure
|
||||||
|
```bash
|
||||||
|
cat dbo.usp_Something.sql | ./bin/sqlai analyze-proc
|
||||||
|
```
|
||||||
|
|
||||||
|
### View
|
||||||
|
```bash
|
||||||
|
cat dbo.vw_Something.sql | ./bin/sqlai analyze-view
|
||||||
|
```
|
||||||
|
|
||||||
|
### Execution Plan
|
||||||
|
- Unterstützt Showplan XML oder Text.
|
||||||
|
```bash
|
||||||
|
./bin/sqlai analyze-plan --file showplan.xml
|
||||||
|
```
|
||||||
|
|
||||||
|
### UTF-8 Migration Plan
|
||||||
|
```bash
|
||||||
|
cat schema_snippet.sql | ./bin/sqlai utf8-migration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prompt Library (Templates)
|
||||||
|
Unter `./prompts/` findest du Copy&Paste-Templates:
|
||||||
|
- `prompts/tsql_review.md`
|
||||||
|
- `prompts/plan_review.md`
|
||||||
|
- `prompts/utf8_migration_runbook.md`
|
||||||
|
- `prompts/indexing_checklist.md`
|
||||||
|
- `prompts/sniffing_stats_playbook.md`
|
||||||
|
- `prompts/proc_refactor_template.md`
|
||||||
|
- `prompts/view_analysis_template.md`
|
||||||
|
|
||||||
|
## Logs
|
||||||
|
- CLI Logs: `./logs/sqlai-YYYY-MM-DD.log`
|
||||||
|
- Bootstrap Logs: `./logs/bootstrap-YYYY-MM-DDTHH:MM:SS.log`
|
||||||
|
- Update Logs: `./logs/update-YYYY-MM-DDTHH:MM:SS.log`
|
||||||
|
|
||||||
|
Die Logs enthalten:
|
||||||
|
- Input-Bytes, Mode, Model
|
||||||
|
- Roh-Metriken aus Ollama (Token Counts, Durations)
|
||||||
|
- Fehler inkl. curl exit codes
|
||||||
|
|
||||||
|
## Auto-Updates aktivieren (systemd --user)
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/.config/systemd/user
|
||||||
|
cp systemd/user/* ~/.config/systemd/user/
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable --now jr-sql-ai-update.timer
|
||||||
|
systemctl --user list-timers | grep jr-sql-ai
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
- **API nicht erreichbar**: Prüfe `docker ps` und ob Port 11434 lokal erreichbar ist (Host-Netz).
|
||||||
|
- **Langsam/OOM**: setze `BASE_MODEL` kleiner (z.B. 7b) und re-run `./scripts/update.sh`.
|
||||||
|
- **Model fehlt**: `./scripts/update.sh` ausführen und prüfen ob `ollama list` im Container das Model zeigt:
|
||||||
|
`docker exec -it ollama ollama list`
|
||||||
130
bin/sqlai
Executable file
130
bin/sqlai
Executable file
@@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
ENV_FILE="${ROOT}/.env"
|
||||||
|
[[ -f "$ENV_FILE" ]] && source "$ENV_FILE"
|
||||||
|
|
||||||
|
: "${OLLAMA_URL:=http://127.0.0.1:11434}"
|
||||||
|
: "${EXPERT_MODEL:=jr-sql-expert}"
|
||||||
|
|
||||||
|
ts() { date -Is; }
|
||||||
|
|
||||||
|
log_dir="${ROOT}/logs"
|
||||||
|
mkdir -p "$log_dir"
|
||||||
|
log_file="${log_dir}/sqlai-$(date -I).log"
|
||||||
|
|
||||||
|
# log everything (stdout+stderr)
|
||||||
|
exec > >(tee -a "$log_file") 2>&1
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage:
|
||||||
|
sqlai <mode> [--file path]
|
||||||
|
Modes:
|
||||||
|
analyze-tsql
|
||||||
|
analyze-proc
|
||||||
|
analyze-view
|
||||||
|
analyze-plan
|
||||||
|
utf8-migration
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
cat query.sql | sqlai analyze-tsql
|
||||||
|
sqlai analyze-plan --file showplan.xml
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
mode="${1:-}"
|
||||||
|
[[ -z "$mode" ]] && { usage; exit 1; }
|
||||||
|
shift || true
|
||||||
|
|
||||||
|
file=""
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--file) file="$2"; shift 2;;
|
||||||
|
*) echo "[$(ts)] ERROR: Unknown arg: $1"; usage; exit 2;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
input=""
|
||||||
|
if [[ -n "$file" ]]; then
|
||||||
|
if [[ ! -f "$file" ]]; then
|
||||||
|
echo "[$(ts)] ERROR: file not found: $file"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
input="$(cat "$file")"
|
||||||
|
else
|
||||||
|
input="$(cat)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${input//[[:space:]]/}" ]]; then
|
||||||
|
echo "[$(ts)] ERROR: empty input"
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$mode" in
|
||||||
|
analyze-tsql)
|
||||||
|
instruction="Analysiere das folgende T-SQL (SQL Server 2022). Finde Performance-Probleme, SARGability, Indizes, Statistiken, Parameter Sniffing Risiken und gib konkrete Verbesserungen."
|
||||||
|
;;
|
||||||
|
analyze-proc)
|
||||||
|
instruction="Analysiere die folgende Stored Procedure (SQL Server 2022). Finde Performance-/Correctness-Risiken, Transaktions-/Locking-Themen, Parameter Sniffing, fehlende Indizes. Gib konkrete Refactorings."
|
||||||
|
;;
|
||||||
|
analyze-view)
|
||||||
|
instruction="Analysiere die folgende View (SQL Server 2022). Prüfe SARGability, Expand/Inlining-Effekte, mögliche Indexing-Optionen (z.B. indexed view falls sinnvoll) und Plan-Auswirkungen."
|
||||||
|
;;
|
||||||
|
analyze-plan)
|
||||||
|
instruction="Analysiere den folgenden SQL Server Execution Plan (XML Showplan oder Text). Identifiziere teure Operatoren, Spills, Warnungen, Kardinalitätsfehler, fehlende Indizes und gib konkrete Fixes."
|
||||||
|
;;
|
||||||
|
utf8-migration)
|
||||||
|
instruction="Erstelle einen Migrationsplan, um Tabellen/Spalten auf UTF-8 umzustellen (UTF-8 enabled collations mit _UTF8). Berücksichtige Abhängigkeiten (FK/PK/Indexes/Computed/Triggers), Risiken und gib eine Schritt-für-Schritt Checkliste."
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[$(ts)] ERROR: unknown mode: $mode"
|
||||||
|
usage
|
||||||
|
exit 5
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
prompt=$(cat <<EOF
|
||||||
|
${instruction}
|
||||||
|
|
||||||
|
---BEGIN INPUT---
|
||||||
|
${input}
|
||||||
|
---END INPUT---
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "[$(ts)] sqlai: MODE=$mode MODEL=$EXPERT_MODEL OLLAMA_URL=$OLLAMA_URL"
|
||||||
|
echo "[$(ts)] sqlai: INPUT_BYTES=$(printf "%s" "$input" | wc -c)"
|
||||||
|
|
||||||
|
payload="$(python - <<'PY'
|
||||||
|
import json, os, sys
|
||||||
|
model=os.environ.get("EXPERT_MODEL","jr-sql-expert")
|
||||||
|
prompt=sys.stdin.read()
|
||||||
|
print(json.dumps({"model": model, "prompt": prompt, "stream": False}, ensure_ascii=False))
|
||||||
|
PY
|
||||||
|
<<<"$prompt")"
|
||||||
|
|
||||||
|
echo "[$(ts)] sqlai: sending request..."
|
||||||
|
resp="$(curl -sS -X POST "${OLLAMA_URL}/api/generate" -H 'Content-Type: application/json' --data-binary "$payload")" || {
|
||||||
|
rc=$?
|
||||||
|
echo "[$(ts)] sqlai: ERROR: curl failed rc=$rc"
|
||||||
|
exit 10
|
||||||
|
}
|
||||||
|
|
||||||
|
python - <<'PY'
|
||||||
|
import json,sys
|
||||||
|
obj=json.loads(sys.stdin.read())
|
||||||
|
print("\n" + (obj.get("response","").rstrip()) + "\n")
|
||||||
|
md = {
|
||||||
|
"total_duration": obj.get("total_duration"),
|
||||||
|
"load_duration": obj.get("load_duration"),
|
||||||
|
"prompt_eval_count": obj.get("prompt_eval_count"),
|
||||||
|
"prompt_eval_duration": obj.get("prompt_eval_duration"),
|
||||||
|
"eval_count": obj.get("eval_count"),
|
||||||
|
"eval_duration": obj.get("eval_duration"),
|
||||||
|
}
|
||||||
|
print("METRICS=" + json.dumps(md, ensure_ascii=False))
|
||||||
|
PY <<<"$resp"
|
||||||
|
|
||||||
|
echo "[$(ts)] sqlai: done"
|
||||||
18
docker-compose.yml
Normal file
18
docker-compose.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
services:
|
||||||
|
ollama:
|
||||||
|
image: ollama/ollama:latest
|
||||||
|
container_name: ollama
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# Uses the host network stack (routing/DNS identical to the host, incl. br0)
|
||||||
|
network_mode: "host"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ollama:/root/.ollama
|
||||||
|
|
||||||
|
environment:
|
||||||
|
# Keep model in memory a bit (optional)
|
||||||
|
OLLAMA_KEEP_ALIVE: "10m"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
ollama:
|
||||||
0
logs/.gitkeep
Normal file
0
logs/.gitkeep
Normal file
25
prompts/indexing_checklist.md
Normal file
25
prompts/indexing_checklist.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Indexing Checklist (SQL Server 2022)
|
||||||
|
|
||||||
|
## Vor dem Index
|
||||||
|
- Welche Query/Workload? (Top N Abfragen)
|
||||||
|
- Welche Filter/Join-Spalten?
|
||||||
|
- Sort/Group By/Distinct? (ORDER BY, GROUP BY)
|
||||||
|
- Häufige Lookups? (Key Lookup / RID Lookup)
|
||||||
|
- Schreiblast hoch? (Index-Overhead)
|
||||||
|
|
||||||
|
## Plausible Index-Regeln
|
||||||
|
- Key Columns: erst Equality predicates, dann Range, dann Join keys
|
||||||
|
- Include Columns: nur für benötigte SELECT-Spalten (Covering)
|
||||||
|
- Filtered Index: wenn Predicate stabil/selektiv (z.B. Status='Active')
|
||||||
|
- Datentypen sauber (keine impliziten Konvertierungen)
|
||||||
|
- Stats: nach großen Loads/Änderungen aktualisieren (gezielt)
|
||||||
|
|
||||||
|
## Validierung
|
||||||
|
- Plan vorher/nachher
|
||||||
|
- Reads/CPU/Duration
|
||||||
|
- Index usage (DMVs) nur als Hinweis, nicht alleinige Wahrheit
|
||||||
|
- Regression Tests / Parameter Sets
|
||||||
|
|
||||||
|
---BEGIN INPUT---
|
||||||
|
<PASTE HERE>
|
||||||
|
---END INPUT---
|
||||||
27
prompts/plan_review.md
Normal file
27
prompts/plan_review.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Execution Plan Review Template (Showplan XML/Text)
|
||||||
|
|
||||||
|
## Kontext (optional)
|
||||||
|
- Query text (falls verfügbar)
|
||||||
|
- Parameterwerte bei Capture
|
||||||
|
- CPU/Duration/Reads/Rowcount bei Capture
|
||||||
|
- Server settings: MAXDOP, Cost Threshold for Parallelism (falls bekannt)
|
||||||
|
|
||||||
|
## Aufgabe
|
||||||
|
1) Kurzfazit
|
||||||
|
2) Hotspots:
|
||||||
|
- Top Operatoren nach Kosten
|
||||||
|
- Spills (Sort/Hash), Warnings
|
||||||
|
- Memory Grant: zu hoch/zu niedrig
|
||||||
|
- Parallelism (CXPACKET/CXCONSUMER Kontext)
|
||||||
|
3) Kardinalität:
|
||||||
|
- wo weicht Estimated vs Actual ab? (wenn Actual vorhanden)
|
||||||
|
- Stats/Histogramm Hinweise
|
||||||
|
4) Fixes:
|
||||||
|
- Query Rewrite
|
||||||
|
- Index/Stats Empfehlungen
|
||||||
|
- Parameter Sniffing Mitigation
|
||||||
|
5) Checkliste für Validierung
|
||||||
|
|
||||||
|
---BEGIN PLAN---
|
||||||
|
<PASTE HERE>
|
||||||
|
---END PLAN---
|
||||||
22
prompts/proc_refactor_template.md
Normal file
22
prompts/proc_refactor_template.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Stored Procedure Review / Refactor Template
|
||||||
|
|
||||||
|
## Kontext (optional)
|
||||||
|
- Aufrufmuster (Parameter, typische Werte):
|
||||||
|
- Isolation Level / Transactions:
|
||||||
|
- Deadlocks/Blocking bekannt? (ja/nein + Hinweise)
|
||||||
|
- Ziel: Latenz, Throughput, Stabilität, Plan-Stabilität
|
||||||
|
|
||||||
|
## Aufgabe
|
||||||
|
1) Kurzfazit
|
||||||
|
2) Detailanalyse
|
||||||
|
- Parameter Sniffing
|
||||||
|
- Temp tables vs table variables
|
||||||
|
- Row-by-row (Cursor, WHILE), UDFs, RBAR
|
||||||
|
- TRY/CATCH + Fehlerbehandlung
|
||||||
|
- Transaktionsumfang (zu groß?), Lock Escalation, Timeouts
|
||||||
|
3) Konkrete Refactorings (mit T-SQL)
|
||||||
|
4) Risiken/Checks/Next steps
|
||||||
|
|
||||||
|
---BEGIN PROC---
|
||||||
|
<PASTE HERE>
|
||||||
|
---END PROC---
|
||||||
30
prompts/sniffing_stats_playbook.md
Normal file
30
prompts/sniffing_stats_playbook.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Parameter Sniffing & Statistics Playbook
|
||||||
|
|
||||||
|
## Symptome
|
||||||
|
- Laufzeit stark schwankend je nach Parameter
|
||||||
|
- Plan ist "gut" für einen Wert, "schlecht" für andere
|
||||||
|
- Große Estimated vs Actual Abweichungen
|
||||||
|
- Memory grants/spills je nach Parameter
|
||||||
|
|
||||||
|
## Diagnose (ohne DB-Zugriff: theoretisch/plan-basiert)
|
||||||
|
- Welche Prädikate sind parameterabhängig?
|
||||||
|
- Gibt es Skew (ein Wert sehr häufig/selten)?
|
||||||
|
- OR-Logik / optional filters (@p IS NULL OR col=@p)?
|
||||||
|
- Implizite Konvertierungen?
|
||||||
|
|
||||||
|
## Gegenmaßnahmen (geordnet von "leicht" zu "hart")
|
||||||
|
1) Query rewrite (SARGability, Splitting optional filters)
|
||||||
|
2) OPTION(RECOMPILE) selektiv
|
||||||
|
3) OPTIMIZE FOR (oder OPTIMIZE FOR UNKNOWN) bewusst
|
||||||
|
4) Zwei Queries / IF branches für stark unterschiedliche Pfade
|
||||||
|
5) Plan guides / forced plan (nur in Ausnahmefällen)
|
||||||
|
6) Stats: update + ggf. filtered stats (wenn passend)
|
||||||
|
|
||||||
|
## Checkliste
|
||||||
|
- Welche Parameter-Sets testen (min/max/typisch)
|
||||||
|
- Regression: CPU/Reads/Duration
|
||||||
|
- Concurrency/Blocking beachten
|
||||||
|
|
||||||
|
---BEGIN INPUT---
|
||||||
|
<PASTE HERE>
|
||||||
|
---END INPUT---
|
||||||
29
prompts/tsql_review.md
Normal file
29
prompts/tsql_review.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# T-SQL Review Template (Copy & Paste)
|
||||||
|
|
||||||
|
> Zweck: schnelle, präzise Analyse einer Abfrage.
|
||||||
|
> Eingabe: T-SQL + (optional) Parameterwerte + (optional) Tabelleninfos.
|
||||||
|
|
||||||
|
## Kontext (optional)
|
||||||
|
- SQL Server Version: 2022
|
||||||
|
- DB Kompatibilitätslevel: ?
|
||||||
|
- Tabellenvolumen grob (Rows): ?
|
||||||
|
- Häufigkeit/Latency Ziel: ?
|
||||||
|
- Parameterwerte (typisch & worst-case): ?
|
||||||
|
|
||||||
|
## Aufgabe
|
||||||
|
Analysiere das T-SQL und liefere:
|
||||||
|
1) **Kurzfazit** (3–6 Bulletpoints)
|
||||||
|
2) **Detailanalyse**:
|
||||||
|
- SARGability (LIKE, Funktionen auf Spalten, CAST/CONVERT, Datentyp-Mismatches)
|
||||||
|
- Joins/Predicates (Reihenfolge, Join Typen)
|
||||||
|
- Kardinalität/Stats (wo schätzt der Optimizer falsch)
|
||||||
|
- Parameter Sniffing Risiko + konkrete Mitigation (z.B. OPTION(RECOMPILE) gezielt, OPTIMIZE FOR, plan guides nur wenn nötig)
|
||||||
|
3) **Konkrete Verbesserungen**:
|
||||||
|
- rewrite (mit kommentiertem SQL)
|
||||||
|
- Index-Vorschläge (nur wenn plausibel; include columns; Filtered Index falls geeignet)
|
||||||
|
4) **Checks**:
|
||||||
|
- welche Messwerte/Plan-Indikatoren prüfen
|
||||||
|
|
||||||
|
---BEGIN T-SQL---
|
||||||
|
<PASTE HERE>
|
||||||
|
---END T-SQL---
|
||||||
27
prompts/utf8_migration_runbook.md
Normal file
27
prompts/utf8_migration_runbook.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# UTF-8 Migration Runbook (SQL Server 2022)
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
Tabellen/Spalten auf UTF-8 umstellen durch Verwendung von UTF-8-enabled Collations (`*_UTF8`).
|
||||||
|
|
||||||
|
## Input (paste)
|
||||||
|
- Aktuelles Schema (CREATE TABLE oder relevante Spalten)
|
||||||
|
- Aktuelle Collations
|
||||||
|
- Abhängigkeiten (FKs, Indexes, Computed Columns, Triggers)
|
||||||
|
- App assumptions (Sortierung, Vergleiche, Case sensitivity)
|
||||||
|
|
||||||
|
---BEGIN INPUT---
|
||||||
|
<PASTE HERE>
|
||||||
|
---END INPUT---
|
||||||
|
|
||||||
|
## Erwartete Ausgabe
|
||||||
|
1) Kurzfazit
|
||||||
|
2) Schritt-für-Schritt Plan (staging -> validate -> cutover -> rollback)
|
||||||
|
3) DDL Snippets:
|
||||||
|
- neue Collation setzen
|
||||||
|
- Rebuild Indizes/Constraints
|
||||||
|
4) Risiken:
|
||||||
|
- Sort-/Compare-Verhalten kann sich ändern
|
||||||
|
- mögliche Indexgrößenänderung
|
||||||
|
- computed columns / persisted computed columns
|
||||||
|
5) Teststrategie:
|
||||||
|
- Vergleichssuites, Known tricky strings, roundtrip tests
|
||||||
23
prompts/view_analysis_template.md
Normal file
23
prompts/view_analysis_template.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# View Analysis Template
|
||||||
|
|
||||||
|
## Kontext (optional)
|
||||||
|
- Wird die View häufig gejoint/weitergefiltert?
|
||||||
|
- Erwartete Selectivity / typische Filter?
|
||||||
|
- Indexed view überhaupt erlaubt/gewünscht? (Schema binding etc.)
|
||||||
|
|
||||||
|
## Aufgabe
|
||||||
|
1) Kurzfazit
|
||||||
|
2) Detailanalyse:
|
||||||
|
- Expand/Inlining Effekte
|
||||||
|
- SARGability und Pushdown von Predicates
|
||||||
|
- Aggregationen/Distinct/Union
|
||||||
|
- Risiken bei Scalar UDFs / Non-deterministic Funktionen
|
||||||
|
3) Verbesserungen:
|
||||||
|
- alternative Definition
|
||||||
|
- Hinweise zu Indizes auf Basistabellen
|
||||||
|
- falls relevant: indexed view Voraussetzungen (nur als Option)
|
||||||
|
4) Risiken/Checks
|
||||||
|
|
||||||
|
---BEGIN VIEW---
|
||||||
|
<PASTE HERE>
|
||||||
|
---END VIEW---
|
||||||
49
scripts/bootstrap.sh
Executable file
49
scripts/bootstrap.sh
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cp -n "${ROOT}/.env.example" "${ROOT}/.env" || true
|
||||||
|
source "${ROOT}/.env"
|
||||||
|
|
||||||
|
ts(){ date -Is; }
|
||||||
|
log_dir="${ROOT}/logs"
|
||||||
|
mkdir -p "$log_dir"
|
||||||
|
log_file="${log_dir}/bootstrap-$(date -Iseconds).log"
|
||||||
|
exec > >(tee -a "$log_file") 2>&1
|
||||||
|
|
||||||
|
echo "[$(ts)] bootstrap: starting (ROOT=$ROOT)"
|
||||||
|
echo "[$(ts)] bootstrap: docker compose up -d"
|
||||||
|
docker compose -f "${ROOT}/docker-compose.yml" up -d
|
||||||
|
|
||||||
|
echo "[$(ts)] bootstrap: waiting for Ollama API at ${OLLAMA_URL} ..."
|
||||||
|
for i in {1..90}; do
|
||||||
|
if curl -sS "${OLLAMA_URL}/api/tags" >/dev/null 2>&1; then
|
||||||
|
echo "[$(ts)] bootstrap: Ollama API is up."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [[ $i -eq 90 ]]; then
|
||||||
|
echo "[$(ts)] bootstrap: ERROR: API did not come up in time."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[$(ts)] bootstrap: pulling base model: ${BASE_MODEL}"
|
||||||
|
docker exec -it ollama ollama pull "${BASE_MODEL}"
|
||||||
|
|
||||||
|
if [[ -n "${EXTRA_MODELS:-}" ]]; then
|
||||||
|
for m in ${EXTRA_MODELS}; do
|
||||||
|
echo "[$(ts)] bootstrap: pulling extra model: $m"
|
||||||
|
docker exec -it ollama ollama pull "$m"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[$(ts)] bootstrap: building expert model: ${EXPERT_MODEL}"
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
sed "s/\${BASE_MODEL}/${BASE_MODEL}/g" "${ROOT}/Modelfile" > "$tmp"
|
||||||
|
docker exec -i ollama ollama create "${EXPERT_MODEL}" -f - < "$tmp"
|
||||||
|
rm -f "$tmp"
|
||||||
|
|
||||||
|
echo "[$(ts)] bootstrap: done"
|
||||||
|
echo "[$(ts)] bootstrap: test:"
|
||||||
|
echo " echo "SELECT 1;" | ${ROOT}/bin/sqlai analyze-tsql"
|
||||||
48
scripts/update.sh
Executable file
48
scripts/update.sh
Executable file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
source "${ROOT}/.env"
|
||||||
|
|
||||||
|
ts(){ date -Is; }
|
||||||
|
log_dir="${ROOT}/logs"
|
||||||
|
mkdir -p "$log_dir"
|
||||||
|
log_file="${log_dir}/update-$(date -Iseconds).log"
|
||||||
|
exec > >(tee -a "$log_file") 2>&1
|
||||||
|
|
||||||
|
echo "[$(ts)] update: starting (ROOT=$ROOT)"
|
||||||
|
echo "[$(ts)] update: pulling docker image(s)"
|
||||||
|
docker compose -f "${ROOT}/docker-compose.yml" pull
|
||||||
|
echo "[$(ts)] update: restarting services"
|
||||||
|
docker compose -f "${ROOT}/docker-compose.yml" up -d
|
||||||
|
|
||||||
|
echo "[$(ts)] update: waiting for Ollama API at ${OLLAMA_URL} ..."
|
||||||
|
for i in {1..90}; do
|
||||||
|
if curl -sS "${OLLAMA_URL}/api/tags" >/dev/null 2>&1; then
|
||||||
|
echo "[$(ts)] update: Ollama API is up."
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [[ $i -eq 90 ]]; then
|
||||||
|
echo "[$(ts)] update: ERROR: API did not come up in time."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[$(ts)] update: pulling base model: ${BASE_MODEL}"
|
||||||
|
docker exec -it ollama ollama pull "${BASE_MODEL}"
|
||||||
|
|
||||||
|
if [[ -n "${EXTRA_MODELS:-}" ]]; then
|
||||||
|
for m in ${EXTRA_MODELS}; do
|
||||||
|
echo "[$(ts)] update: pulling extra model: $m"
|
||||||
|
docker exec -it ollama ollama pull "$m"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[$(ts)] update: rebuilding expert model: ${EXPERT_MODEL}"
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
sed "s/\${BASE_MODEL}/${BASE_MODEL}/g" "${ROOT}/Modelfile" > "$tmp"
|
||||||
|
docker exec -i ollama ollama create "${EXPERT_MODEL}" -f - < "$tmp"
|
||||||
|
rm -f "$tmp"
|
||||||
|
|
||||||
|
echo "[$(ts)] update: complete"
|
||||||
7
systemd/user/jr-sql-ai-update.service
Normal file
7
systemd/user/jr-sql-ai-update.service
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Update Ollama runtime + models (jr-sql-ai)
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
WorkingDirectory=%h/jr-sql-ai
|
||||||
|
ExecStart=%h/jr-sql-ai/scripts/update.sh
|
||||||
9
systemd/user/jr-sql-ai-update.timer
Normal file
9
systemd/user/jr-sql-ai-update.timer
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Daily update timer for jr-sql-ai
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=daily
|
||||||
|
Persistent=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
Reference in New Issue
Block a user