Skip to content

feat: PK metadata detection, save preserves original query, AI Assistant persistence#215

Open
kix007 wants to merge 2 commits into
mainfrom
feat/pk-metadata-save-preserve-scroll
Open

feat: PK metadata detection, save preserves original query, AI Assistant persistence#215
kix007 wants to merge 2 commits into
mainfrom
feat/pk-metadata-save-preserve-scroll

Conversation

@kix007
Copy link
Copy Markdown
Collaborator

@kix007 kix007 commented Jun 5, 2026

Summary

  • PK detection now queries real DB metadata from information_schema.table_constraints (PostgreSQL/MySQL) and PRAGMA table_info (SQLite) instead of relying solely on name heuristics
  • Unified getPrimaryKey helper used across all CRUD operations
  • Save no longer replaces custom query results with SELECT * FROM table — re-runs the user's original SELECT via lastSelectQueryRef
  • Schema-qualified table PK candidates use base table name (config_id not ansible.config_id)
  • Fallback UPDATE WHERE uses _original snapshot to prevent 0-row updates
  • Grid scrolls to saved/inserted record after save
  • AI Assistant: extracted shared callAI to src/lib/ai.ts, wired AIAssistantDialog to real provider (no longer setTimeout stub), added AI settings persistence to settingsStore
  • Roadmap: removed shipped items (vault hardening, AI assistant, schema-aware row editor, ER diagram)

Related issue

Changes

  • PK detection now queries real DB metadata from information_schema.table_constraints (PostgreSQL/MySQL) and PRAGMA table_info (SQLite) instead of relying solely on name heuristics
  • Unified getPrimaryKey helper used across all CRUD operations
  • Save no longer replaces custom query results with SELECT * FROM table — re-runs the user's original SELECT via lastSelectQueryRef
  • Schema-qualified table PK candidates use base table name (config_id not ansible.config_id)
  • Fallback UPDATE WHERE uses _original snapshot to prevent 0-row updates
  • Grid scrolls to saved/inserted record after save
  • AI Assistant: extracted shared callAI to src/lib/ai.ts, wired AIAssistantDialog to real provider (no longer setTimeout stub), added AI settings persistence to settingsStore
  • Roadmap: removed shipped items (vault hardening, AI assistant, schema-aware row editor, ER diagram)

Testing notes

Checklist

  • I built the app locally (npm run tauri dev or npm run tauri build) and verified the change works.
  • Frontend typecheck passes (npx tsc --noEmit).
  • Rust build passes (cargo check --manifest-path src-tauri/Cargo.toml).
  • If I added a new #[tauri::command], I registered it in src-tauri/src/lib.rs's generate_handler!.
  • If user-visible: I added a line to CHANGELOG.md under ## [Unreleased].
  • If this touches storage.rs, updater.rs, capabilities/, or the AI assistant code path, I flagged it in the summary above.

Summary by CodeRabbit

  • New Features

    • AI Assistant dialog now generates SQL queries using configured provider
    • Primary key detection improvements for better row editing accuracy
    • ER diagram defaults to compact view (PK/FK columns only)
    • Grid auto-scrolls to saved or newly inserted rows
  • Bug Fixes

    • Editing and saving rows now re-runs your original query instead of a generic table scan
    • Foreign key metadata now auto-loads and caches after table queries
    • Browser native right-click menu restored
    • Add-row flow improved with dedicated connection handling
  • Documentation

    • Updated roadmap and changelog with completed features

keens007 added 2 commits June 5, 2026 15:44
…ant persistence

- PK detection now queries real DB metadata from
  information_schema.table_constraints (PostgreSQL/MySQL) and
  PRAGMA table_info (SQLite) instead of relying solely on name heuristics
- Unified getPrimaryKey helper used across all CRUD operations
- Save no longer replaces custom query results with SELECT * FROM table
  — re-runs the user's original SELECT via lastSelectQueryRef
- Schema-qualified table PK candidates use base table name (config_id
  not ansible.config_id)
- Fallback UPDATE WHERE uses _original snapshot to prevent 0-row updates
- Grid scrolls to saved/inserted record after save
- AI Assistant: extracted shared callAI to src/lib/ai.ts, wired
  AIAssistantDialog to real provider (no longer setTimeout stub),
  added AI settings persistence to settingsStore
- Roadmap: removed shipped items (vault hardening, AI assistant,
  schema-aware row editor, ER diagram)
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 5, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
queryden Error Error Jun 5, 2026 1:45pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR enhances QueryDen with primary key metadata discovery across PostgreSQL, MySQL, and SQLite, refactors row editing to preserve original queries and scroll to changes, prevents execution race conditions, and wires a real AI Assistant dialog with settings persistence.

Changes

Row Editing and Execution Flow Improvements

Layer / File(s) Summary
Primary Key Metadata Discovery
src/components/explorer/DatabaseExplorer.tsx
TableDetails now includes primaryKeys field populated by engine-specific queries: PostgreSQL/Cockroach query information_schema.table_constraints and key_column_usage; MySQL/MariaDB query key_column_usage for PRIMARY constraint; SQLite uses PRAGMA table_info filtered by pk ordinal.
Execution Generation Tracking
src/components/layout/MainContent.tsx
Execution flow tracks per-run generation via executionGenRef to prevent stale async completions from updating UI after cancellation or newer executions; guards added on isExecuting updates and cleanup logic.
Schema Metadata & PK-aware Row Operations
src/components/layout/MainContent.tsx
tableSchema now stores primaryKeys; new getPrimaryKey helper prefers database metadata and falls back to heuristic column names derived from activeTableName; handleUpdateRow and handleDeleteRow use unified PK resolver for accurate row matching.
Save Flow with Original Query & Grid Scrolling
src/components/layout/MainContent.tsx, src/components/results/ResultsPanel.tsx
handleSave captures original SELECT before writes, uses _original row snapshots for UPDATE WHERE fallback, refreshes results with the same query, and scrolls grid to affected row; ResultsPanel adds grid-scroll-to-row event listener and snapshots _original values during edit.
Add Row Flow Refactoring
src/components/layout/MainContent.tsx, src/components/results/ResultsPanel.tsx
handleAddRow replaced with direct insert + refresh using dedicated save-scoped connection and SELECT fallback; AddRowModal wiring updated to control localOnly flag explicitly.

AI Assistant Implementation and Settings

Layer / File(s) Summary
AI Core Function and Dialog Integration
src/lib/ai.ts, src/components/tools/AIAssistantDialog.tsx, src/components/results/VisualOptimizer.tsx
New callAI async function reads AI config, builds provider-specific endpoints/headers/payloads for OpenAI/Anthropic/Google/local, enforces 30s timeout, and parses provider-specific response fields; AIAssistantDialog calls real callAI with try/catch, displays errors, and hides header line when unconfigured; VisualOptimizer imports callAI instead of defining local version.
AI Settings Persistence & Store
src/store/settingsStore.ts, src/store/aiStore.ts, src/components/settings/SettingsDialog.tsx
DBSettings extended with AI fields (provider, apiKey, model, endpoint, enabled); AISettings introduces persistAI helper to sync useAI state into useSettings; SettingsDialog handlers persist changes via persistAI; app init syncs stored AI settings into useAI state; default model updated to "gpt-5.5".

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • openidle-dev/queryden#209: Both PRs update ER diagram and PostgreSQL/MySQL/SQLite metadata introspection for PK/FK handling and switch FK queries to use updated database catalog sources.

Poem

A rabbit hops through databases bright, 🐰
Finding primary keys with all its might,
Saving edits with queries so true,
AI Assistant now works—no more fake debut!
Scrolling to rows where changes do light. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the three main changes: primary key metadata detection, preserving the original query on save, and AI Assistant persistence.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/pk-metadata-save-preserve-scroll

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/layout/MainContent.tsx (1)

2554-2572: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Provider-specific branching uses the wrong connection context.

These branches use activeConnection.type, but save/add now execute on resolved conn (tab target can differ). If types differ, wrong SQL path is chosen.

Proposed fix
-        if (["postgres", "supabase", "cockroach", "mysql", "mariadb"].includes(activeConnection.type)) {
+        if (["postgres", "supabase", "cockroach", "mysql", "mariadb"].includes(conn.type)) {
...
-        } else if (activeConnection.type === "sqlite") {
+        } else if (conn.type === "sqlite") {
...
-        if (activeConnection.type === "mysql" || activeConnection.type === "mariadb") {
+        if (conn.type === "mysql" || conn.type === "mariadb") {

Also applies to: 2785-2786

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/layout/MainContent.tsx` around lines 2554 - 2572, The
provider-specific branching logic is checking activeConnection.type to determine
which SQL path to use, but the database operations are being executed on the
resolved conn object (which may differ from activeConnection if targeting a
different tab). Replace the activeConnection.type checks in the conditional
statements (at the lines checking for postgres, supabase, cockroach, mysql,
mariadb, and sqlite) with checks against the actual resolved connection type
that is being used for the database operations, ensuring the correct SQL dialect
is selected based on the connection being executed rather than the currently
active connection.
🧹 Nitpick comments (2)
src/components/tools/AIAssistantDialog.tsx (1)

30-58: ⚖️ Poor tradeoff

Consider UX: Dialog closes immediately after success.

Line 52 closes the dialog immediately after updating the query. This means users don't see any success confirmation or the AI response before the dialog disappears. Consider showing a brief success state or allowing users to review the generated SQL before closing.

💡 Optional UX improvement

Add a success state and delay closing:

       const result = await callAI(systemPrompt, userPrompt);
       if (result) {
         onUpdateQuery(result);
+        // Show success briefly before closing
+        setTimeout(() => onClose(), 500);
+      } else {
+        onClose();
       }
-      onClose();

Or allow users to review before accepting:

  • Add a generatedSQL state
  • Show the generated SQL in a preview area
  • Add "Accept" and "Cancel" buttons
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/tools/AIAssistantDialog.tsx` around lines 30 - 58,
handleGenerate currently calls onUpdateQuery(result) and onClose() immediately,
closing the dialog before the user can see or confirm the AI output; change this
to save the AI response into a new generatedSQL state (setGeneratedSQL(result))
instead of immediately calling onClose, remove the immediate
onUpdateQuery/onClose, and surface a preview in the dialog with "Accept" and
"Cancel" actions where Accept calls onUpdateQuery(generatedSQL) then onClose and
Cancel clears generatedSQL; alternatively implement a brief success state/toast
and a short delay before calling onClose if an explicit review step is
undesired.
src/lib/ai.ts (1)

76-86: ⚡ Quick win

Silent failure on response parsing.

Lines 76-85 use optional chaining to extract the AI response, returning an empty string "" if parsing fails (line 85). This silently swallows malformed responses, making debugging difficult. Consider logging a warning or throwing an error when the expected response shape is missing.

🛠️ Suggested improvement
   if (ai.provider === "openai") {
-    return result.choices?.[0]?.message?.content || "";
+    const content = result.choices?.[0]?.message?.content;
+    if (!content) {
+      console.warn("[callAI] OpenAI response missing expected content:", result);
+    }
+    return content || "";
   } else if (ai.provider === "anthropic") {
-    return result.content?.[0]?.text || "";
+    const text = result.content?.[0]?.text;
+    if (!text) {
+      console.warn("[callAI] Anthropic response missing expected text:", result);
+    }
+    return text || "";
   } else if (ai.provider === "google") {
-    return result.candidates?.[0]?.content?.parts?.[0]?.text || "";
+    const text = result.candidates?.[0]?.content?.parts?.[0]?.text;
+    if (!text) {
+      console.warn("[callAI] Google response missing expected text:", result);
+    }
+    return text || "";
   } else if (ai.provider === "local") {
-    return result.message?.content || "";
+    const content = result.message?.content;
+    if (!content) {
+      console.warn("[callAI] Local AI response missing expected content:", result);
+    }
+    return content || "";
   }
-  return "";
+  console.warn("[callAI] Unknown provider, returning empty response");
+  return "";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/ai.ts` around lines 76 - 86, The response-parsing block that reads
ai.provider and returns parts of result currently falls back to an empty string
on malformed responses, which hides errors; update the parsing logic (the branch
that checks ai.provider and reads result) to detect when the expected shape is
missing and either log a warning including the provider and the full result
(e.g., JSON.stringify(result)) or throw a descriptive error mentioning
ai.provider and the unexpected result shape instead of silently returning "".
Ensure you reference the same identifiers (ai.provider and result) so the fix
applies to the existing branches for "openai", "anthropic", "google", and
"local".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 72-73: There are two identical "### Removed" headings under the
"Unreleased" section causing MD024; locate the duplicate "### Removed" heading
(the second occurrence) and either remove it or merge its bullet(s) into the
first "### Removed" list so only one "### Removed" heading remains; ensure the
bullets mentioning "Vault crypto hardening", "Schema-aware row editor", and "ER
Diagram" are preserved under the single heading.

In `@src/components/layout/MainContent.tsx`:
- Around line 2039-2043: The finally block currently clears
cancelFlagRef.current unconditionally which can clear a newer run's cancel
state; change the cleanup to only run when the finished execution generation
matches the active one by wrapping the cancelFlagRef.current = false (and the
existing setIsExecuting(false)/isExecutingRef.current = false) in the same guard
using gen === executionGenRef.current so only the matching generation resets the
cancel flag and execution state.
- Around line 2365-2373: getPrimaryKey currently returns only the first matching
column which collapses composite primary keys; change the function (e.g., rename
to getPrimaryKeys) to return string[] | undefined and collect all matching PK
columns instead of the first: (1) if tableSchema?.primaryKeys exists return all
primaryKeys that are present in the provided columns array; (2) otherwise build
the candidate set (including `${baseTableName.toLowerCase()}_id`) and return all
columns that case-insensitively match any candidate; (3) update all callers that
relied on a single PK to accept multiple PK columns and construct WHERE/matching
clauses by joining those PK conditions with AND so updates/deletes correctly
target composite-key rows.

In `@src/store/aiStore.ts`:
- Line 21: The default AI model value is invalid ("gpt-5.5"); update the `model`
property in the aiStore default settings to a valid OpenAI model name (for
example "gpt-4o", "gpt-4-turbo", or "gpt-3.5-turbo") and make the same change
where the same default appears in settingsStore (the mirrored `model` property
referenced in settingsStore.ts) so both defaults match a supported model.

---

Outside diff comments:
In `@src/components/layout/MainContent.tsx`:
- Around line 2554-2572: The provider-specific branching logic is checking
activeConnection.type to determine which SQL path to use, but the database
operations are being executed on the resolved conn object (which may differ from
activeConnection if targeting a different tab). Replace the
activeConnection.type checks in the conditional statements (at the lines
checking for postgres, supabase, cockroach, mysql, mariadb, and sqlite) with
checks against the actual resolved connection type that is being used for the
database operations, ensuring the correct SQL dialect is selected based on the
connection being executed rather than the currently active connection.

---

Nitpick comments:
In `@src/components/tools/AIAssistantDialog.tsx`:
- Around line 30-58: handleGenerate currently calls onUpdateQuery(result) and
onClose() immediately, closing the dialog before the user can see or confirm the
AI output; change this to save the AI response into a new generatedSQL state
(setGeneratedSQL(result)) instead of immediately calling onClose, remove the
immediate onUpdateQuery/onClose, and surface a preview in the dialog with
"Accept" and "Cancel" actions where Accept calls onUpdateQuery(generatedSQL)
then onClose and Cancel clears generatedSQL; alternatively implement a brief
success state/toast and a short delay before calling onClose if an explicit
review step is undesired.

In `@src/lib/ai.ts`:
- Around line 76-86: The response-parsing block that reads ai.provider and
returns parts of result currently falls back to an empty string on malformed
responses, which hides errors; update the parsing logic (the branch that checks
ai.provider and reads result) to detect when the expected shape is missing and
either log a warning including the provider and the full result (e.g.,
JSON.stringify(result)) or throw a descriptive error mentioning ai.provider and
the unexpected result shape instead of silently returning "". Ensure you
reference the same identifiers (ai.provider and result) so the fix applies to
the existing branches for "openai", "anthropic", "google", and "local".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fb16765a-0c4e-4941-bd2e-e316dffc533e

📥 Commits

Reviewing files that changed from the base of the PR and between 17c9b47 and e044a93.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • src/components/explorer/DatabaseExplorer.tsx
  • src/components/layout/MainContent.tsx
  • src/components/results/ResultsPanel.tsx
  • src/components/results/VisualOptimizer.tsx
  • src/components/settings/SettingsDialog.tsx
  • src/components/tools/AIAssistantDialog.tsx
  • src/lib/ai.ts
  • src/store/aiStore.ts
  • src/store/settingsStore.ts
  • website/src/content/docs/ai/byo-key.mdx
  • website/src/pages/roadmap.astro
💤 Files with no reviewable changes (1)
  • website/src/pages/roadmap.astro

Comment thread CHANGELOG.md
Comment on lines +72 to +73
### Removed
- **Roadmap items removed as addressed.** "Vault crypto hardening" (#14, #15), "Schema-aware row editor" (#50), and "ER Diagram" (#51) removed from the website roadmap — vault hardening, schema-aware FK dropdowns, NOT NULL validation, and ER diagram support in this release subsume those feature requests.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Duplicate heading level under Unreleased (### Removed).

Line 72 introduces a second ### Removed heading in the same section, which triggers MD024 and can break docs tooling/navigation.

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 72-72: Multiple headings with the same content

(MD024, no-duplicate-heading)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` around lines 72 - 73, There are two identical "### Removed"
headings under the "Unreleased" section causing MD024; locate the duplicate "###
Removed" heading (the second occurrence) and either remove it or merge its
bullet(s) into the first "### Removed" list so only one "### Removed" heading
remains; ensure the bullets mentioning "Vault crypto hardening", "Schema-aware
row editor", and "ER Diagram" are preserved under the single heading.

Comment on lines +2039 to 2043
cancelFlagRef.current = false;
if (gen === executionGenRef.current) {
setIsExecuting(false);
isExecutingRef.current = false;
isExecutingRef.current = false;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard cancel-state cleanup to the active execution generation.

On Line 2039, cancelFlagRef.current is reset unconditionally in finally. A stale execution can clear cancel state for a newer in-flight run, causing cancel to be ignored intermittently.

Proposed fix
-      cancelFlagRef.current = false;
-      if (gen === executionGenRef.current) {
+      if (gen === executionGenRef.current) {
+        cancelFlagRef.current = false;
         setIsExecuting(false);
         isExecutingRef.current = false;
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cancelFlagRef.current = false;
if (gen === executionGenRef.current) {
setIsExecuting(false);
isExecutingRef.current = false;
isExecutingRef.current = false;
}
if (gen === executionGenRef.current) {
cancelFlagRef.current = false;
setIsExecuting(false);
isExecutingRef.current = false;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/layout/MainContent.tsx` around lines 2039 - 2043, The finally
block currently clears cancelFlagRef.current unconditionally which can clear a
newer run's cancel state; change the cleanup to only run when the finished
execution generation matches the active one by wrapping the
cancelFlagRef.current = false (and the existing
setIsExecuting(false)/isExecutingRef.current = false) in the same guard using
gen === executionGenRef.current so only the matching generation resets the
cancel flag and execution state.

Comment on lines +2365 to +2373
const getPrimaryKey = useCallback((columns: string[]): string | undefined => {
if (tableSchema?.primaryKeys && tableSchema.primaryKeys.length > 0) {
const found = tableSchema.primaryKeys.find(pk => columns.includes(pk));
if (found) return found;
}
if (!activeTableName) return undefined;
const baseTableName = activeTableName.includes('.') ? activeTableName.split('.').pop()! : activeTableName;
const candidates = new Set(["id", "uuid", "uid", "pk", "row_id", "object_id", "key", "code", "_id", `${baseTableName.toLowerCase()}_id`]);
return columns.find(c => candidates.has(c.toLowerCase()));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Composite primary keys are collapsed to one column.

getPrimaryKey returns only the first matching PK column. For composite PK tables, update/delete matching can target multiple rows incorrectly.

Proposed direction
-const getPrimaryKey = useCallback((columns: string[]): string | undefined => {
-  if (tableSchema?.primaryKeys && tableSchema.primaryKeys.length > 0) {
-    const found = tableSchema.primaryKeys.find(pk => columns.includes(pk));
-    if (found) return found;
-  }
+const getPrimaryKeys = useCallback((columns: string[]): string[] => {
+  if (tableSchema?.primaryKeys?.length) {
+    const found = tableSchema.primaryKeys.filter(pk => columns.includes(pk));
+    if (found.length) return found;
+  }
   ...
-  return columns.find(c => candidates.has(c.toLowerCase()));
-}, [tableSchema, activeTableName]);
+  const heuristic = columns.find(c => candidates.has(c.toLowerCase()));
+  return heuristic ? [heuristic] : [];
+}, [tableSchema, activeTableName]);

Then build WHERE/row matching using all returned PK columns with AND.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/layout/MainContent.tsx` around lines 2365 - 2373,
getPrimaryKey currently returns only the first matching column which collapses
composite primary keys; change the function (e.g., rename to getPrimaryKeys) to
return string[] | undefined and collect all matching PK columns instead of the
first: (1) if tableSchema?.primaryKeys exists return all primaryKeys that are
present in the provided columns array; (2) otherwise build the candidate set
(including `${baseTableName.toLowerCase()}_id`) and return all columns that
case-insensitively match any candidate; (3) update all callers that relied on a
single PK to accept multiple PK columns and construct WHERE/matching clauses by
joining those PK conditions with AND so updates/deletes correctly target
composite-key rows.

Comment thread src/store/aiStore.ts
provider: "openai",
apiKey: "",
model: "gpt-4o",
model: "gpt-5.5",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Invalid default AI model name.

The default model is set to "gpt-5.5", which does not match any known OpenAI model. This mirrors the same issue in settingsStore.ts line 155. The value should be updated to a valid model such as "gpt-4o", "gpt-4-turbo", or "gpt-3.5-turbo".

🛠️ Suggested fix
-  model: "gpt-5.5",
+  model: "gpt-4o",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
model: "gpt-5.5",
model: "gpt-4o",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/store/aiStore.ts` at line 21, The default AI model value is invalid
("gpt-5.5"); update the `model` property in the aiStore default settings to a
valid OpenAI model name (for example "gpt-4o", "gpt-4-turbo", or
"gpt-3.5-turbo") and make the same change where the same default appears in
settingsStore (the mirrored `model` property referenced in settingsStore.ts) so
both defaults match a supported model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants