feat: add AI data validation, test data generator, index advisor, and snapshots
Four new killer features leveraging AI (Ollama) and PostgreSQL internals: - Data Validation: describe quality rules in natural language, AI generates SQL to find violations, run with pass/fail results and sample violations - Test Data Generator: right-click table to generate realistic FK-aware test data with AI, preview before inserting in a transaction - Index Advisor: analyze pg_stat tables + AI recommendations for CREATE/DROP INDEX with one-click apply - Data Snapshots: export selected tables to JSON (FK-ordered), restore from file with optional truncate in a transaction Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
73
src/hooks/use-data-generator.ts
Normal file
73
src/hooks/use-data-generator.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import {
|
||||
generateTestDataPreview,
|
||||
insertGeneratedData,
|
||||
onDataGenProgress,
|
||||
} from "@/lib/tauri";
|
||||
import type { GenerateDataParams, DataGenProgress, GeneratedDataPreview } from "@/types";
|
||||
|
||||
export function useDataGenerator() {
|
||||
const [progress, setProgress] = useState<DataGenProgress | null>(null);
|
||||
const genIdRef = useRef<string>("");
|
||||
|
||||
const previewMutation = useMutation({
|
||||
mutationFn: ({
|
||||
params,
|
||||
genId,
|
||||
}: {
|
||||
params: GenerateDataParams;
|
||||
genId: string;
|
||||
}) => {
|
||||
genIdRef.current = genId;
|
||||
setProgress(null);
|
||||
return generateTestDataPreview(params, genId);
|
||||
},
|
||||
});
|
||||
|
||||
const insertMutation = useMutation({
|
||||
mutationFn: ({
|
||||
connectionId,
|
||||
preview,
|
||||
}: {
|
||||
connectionId: string;
|
||||
preview: GeneratedDataPreview;
|
||||
}) => insertGeneratedData(connectionId, preview),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const unlistenPromise = onDataGenProgress((p) => {
|
||||
if (p.gen_id === genIdRef.current) {
|
||||
setProgress(p);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
unlistenPromise.then((unlisten) => unlisten());
|
||||
};
|
||||
}, []);
|
||||
|
||||
const previewRef = useRef(previewMutation);
|
||||
previewRef.current = previewMutation;
|
||||
const insertRef = useRef(insertMutation);
|
||||
insertRef.current = insertMutation;
|
||||
|
||||
const reset = useCallback(() => {
|
||||
previewRef.current.reset();
|
||||
insertRef.current.reset();
|
||||
setProgress(null);
|
||||
genIdRef.current = "";
|
||||
}, []);
|
||||
|
||||
return {
|
||||
generatePreview: previewMutation.mutate,
|
||||
preview: previewMutation.data as GeneratedDataPreview | undefined,
|
||||
isGenerating: previewMutation.isPending,
|
||||
generateError: previewMutation.error ? String(previewMutation.error) : null,
|
||||
insertData: insertMutation.mutate,
|
||||
insertedRows: insertMutation.data as number | undefined,
|
||||
isInserting: insertMutation.isPending,
|
||||
insertError: insertMutation.error ? String(insertMutation.error) : null,
|
||||
progress,
|
||||
reset,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user