pgLabII/pgLabII/QueryToolPlan.md
2025-09-06 13:32:51 +02:00

6.3 KiB
Raw Blame History

Features

  • Is a part of the SingleDatabaseWindow
  • It's view should go in QueryToolView.axaml
  • Uses mvvm
  • AvaloniaEdit should be used as a query editor

Editor

  • Use CodeEditorView
  • We want to be able to open and save .sql files with the editor

Result grid

  • Use an Avalonia.Controls.DataGrid
  • The columns will change on runtime so it should be able to get the column count captions and data types from the viewmodel
  • We want to be able to sort the columns
  • We want to be able to filter the rows by defining conditions for the columns
  • We want to be able to copy the rows to the clipboard
  • We want to be able to customize cell rendering to use different colors for types and also do special things like rendering booleans as green checks and red crosses
  • Be aware results may contain many rows, we should make a decision on how to handle this
  • We want to be able to save the results to a file

Step-by-step plan to create the Query Tool

  1. Add QueryToolView to the UI shell.

    • Place the view in pgLabII\Views\QueryToolView.axaml and include it within SingleDatabaseWindow as a child region/panel. Ensure DataContext is set to QueryToolViewModel.
    • Confirm MVVM wiring: commands and properties will be bound from the ViewModel.
  2. Integrate the SQL editor.

    • Embed AvaloniaEdit editor in the top area of QueryToolView.
    • Bind editor text to a ViewModel property (e.g., UserSql).
    • Provide commands for OpenSqlFile and SaveSqlFile; wire to toolbar/buttons and standard shortcuts (Ctrl+O/Ctrl+S).
    • Ensure file filters default to .sql and that encoding/line-endings preserve content when saving.
  3. Add a results toolbar for query operations.

    • Buttons/controls: Run, Cancel (optional), "Load more", Auto-load on scroll toggle, Export..., and a compact status/summary text (e.g., "Showing X of Y rows").
    • Bind to RunQuery, LoadMore, ExportResults, AutoLoadMore, ResultSummary, and Status properties.
  4. Add the result grid using Avalonia.Controls.DataGrid.

    • Enable row and column virtualization. Keep cell templates lightweight to preserve performance.
    • Start with AutoGenerateColumns=true; later switch to explicit columns if custom cell templates per type are needed.
    • Bind Items to a read-only observable collection of row objects (e.g., Rows).
    • Enable extended selection and clipboard copy.
  5. Support dynamic columns and types from the ViewModel.

    • Expose a Columns metadata collection (names, data types, display hints) from the ViewModel.
    • On first page load, update metadata so the grid can reflect the current querys shape.
    • If AutoGenerateColumns is disabled, construct DataGrid columns based on metadata (text, number, date, boolean with check/cross visuals).
  6. Sorting model.

    • On column header sort request, send sort descriptor(s) to the ViewModel.
    • Re-run the query via server-side ORDER BY by wrapping the user SQL as a subquery and applying sort expressions.
    • Reset paging when sort changes (reload from page 1).
    • Clearly indicate if sorting is client-side (fallback) and only affects loaded rows.
  7. Filtering model.

    • Provide a simple filter row/panel to define per-column conditions.
    • Convert user-entered filters to a filter descriptor list in the ViewModel.
    • Prefer server-side WHERE by wrapping the user SQL; reset paging when filters change.
    • If server-side wrapping is not possible for a given statement, apply client-side filtering to the currently loaded subset and warn that the filter is partial.
  8. Data paging and virtualization (for 100k+ rows).

    • Choose a default page size of 1000 rows (range 5002000).
    • On RunQuery: clear rows, reset page index, set CanLoadMore=true, fetch page 1.
    • "Load more" fetches the next page and appends. Enable infinite scroll optionally when near the end.
    • Display summary text: "Showing N of M+ rows" when total is known; otherwise "Showing N rows".
    • Consider a cap on retained rows (e.g., last 1020k) if memory is a concern.
  9. Query execution abstraction.

    • Use a service (e.g., IQueryExecutor) to run database calls.
    • Provide: FetchPageAsync(userSql, sort, filters, page, size, ct) and StreamAllAsync(userSql, sort, filters, ct) for export.
    • Wrap user SQL as a subquery to inject WHERE/ORDER BY/LIMIT/OFFSET safely; trim trailing semicolons.
    • Prefer keyset pagination when a stable ordered key exists.
  10. Export/Save results.

  • Export should re-execute the query and stream the full result set directly from the database to CSV/TSV/JSON.
  • Do not export from the grid items because the grid may contain only a subset of rows.
  • Provide a Save As dialog with format choice and destination path.
  1. Copy to clipboard and selection.
  • Enable extended row selection in the grid; support Ctrl+C to copy selected rows.
  • Provide a toolbar "Copy" button as an alternative entry point.
  1. Status, cancellation, and errors.
  • Show progress/state (Running, Idle, Loading page k, Cancelled, Error).
  • Support cancellation tokens for long-running queries and paging operations.
  • Surface exceptions as non-blocking notifications and preserve the last successful rows.
  1. Theming and custom cell rendering.
  • Apply subtle coloring by type (numbers, dates, strings) via cell styles or templates.
  • Render booleans as green checks/red crosses with minimal template overhead to keep virtualization effective.
  1. Wiring in SingleDatabaseWindow.
  • Add a dedicated region/tab/panel for the Query Tool.
  • Ensure lifetime management of the QueryToolViewModel aligns with the connection/session scope.
  • Provide the active connection context/service to the ViewModel (DI or constructor).
  1. Testing and verification.
  • Manual test: small query, large query (100k rows), sorting, filtering, load more, infinite scroll, export, copy, boolean rendering.
  • Edge cases: empty results, wide tables (many columns), slow network, cancellation mid-page, schema change between pages.
  • Performance check: scroll smoothness, memory growth under repeated paging, export throughput.
  1. Documentation and UX notes.
  • In help/tooltip, clarify that sorting/filtering are server-side when possible; otherwise they apply only to loaded rows.
  • Show a banner when results are truncated by paging limits and how to load more.