-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: combine exec and query database tools
- Combine the `Run Database Query` and `Exec Database Statement` tools into a single `Run Database Command` tool that allows for executing both statements and queries. The new tool returns the raw SQL output instead of JSON - Shell out to the sqlite3 binary instead of using a dependency-free go module - Add the `list_database_tables` and `list_database_table_rows` system tools to retain database support in the user UI Signed-off-by: Nick Hale <[email protected]>
- Loading branch information
Showing
12 changed files
with
211 additions
and
177 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
|
||
"github.com/google/shlex" | ||
) | ||
|
||
// RunDatabaseCommand runs a sqlite3 command against the database and returns the output from the sqlite3 CLI. | ||
func RunDatabaseCommand(ctx context.Context, dbFile *os.File, sqlite3Args string) (string, error) { | ||
// Remove the "sqlite3" prefix and trim whitespace | ||
sqlite3Args = strings.TrimPrefix(strings.TrimSpace(sqlite3Args), "sqlite3") | ||
|
||
// Split the arguments using shlex | ||
args, err := shlex.Split(sqlite3Args) | ||
if err != nil { | ||
return "", fmt.Errorf("error parsing sqlite3 args: %w", err) | ||
} | ||
|
||
// Append the database file name as the first argument | ||
args = append([]string{dbFile.Name()}, args...) | ||
|
||
// Build the sqlite3 command | ||
cmd := exec.CommandContext(ctx, "sqlite3", args...) | ||
|
||
// Redirect command output | ||
var stdout, stderr bytes.Buffer | ||
cmd.Stdout = &stdout | ||
cmd.Stderr = &stderr | ||
|
||
// Run the command and capture errors | ||
if err := cmd.Run(); err != nil { | ||
return "", fmt.Errorf("error executing sqlite3: %w, stderr: %s", err, stderr.String()) | ||
} | ||
|
||
return stdout.String(), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"strings" | ||
) | ||
|
||
type Output struct { | ||
Columns []string `json:"columns"` | ||
Rows []map[string]any `json:"rows"` | ||
} | ||
|
||
// ListDatabaseTableRows lists all rows from the specified table using RunDatabaseCommand and returns a JSON object containing the results. | ||
func ListDatabaseTableRows(ctx context.Context, dbFile *os.File, table string) (string, error) { | ||
if table == "" { | ||
return "", fmt.Errorf("table name cannot be empty") | ||
} | ||
|
||
// Build the query to fetch all rows from the table | ||
query := fmt.Sprintf("SELECT * FROM %q;", table) | ||
|
||
// Execute the query using RunDatabaseCommand | ||
rawOutput, err := RunDatabaseCommand(ctx, dbFile, fmt.Sprintf("%q", query)) | ||
if err != nil { | ||
return "", fmt.Errorf("error executing query for table %q: %w", table, err) | ||
} | ||
|
||
// Split raw output into rows | ||
lines := strings.Split(strings.TrimSpace(rawOutput), "\n") | ||
if len(lines) == 0 { | ||
return "", fmt.Errorf("no output from query for table %q", table) | ||
} | ||
|
||
// The first line contains column names | ||
columns := strings.Split(lines[0], "|") | ||
output := Output{ | ||
Columns: columns, | ||
Rows: []map[string]any{}, | ||
} | ||
|
||
// Process the remaining lines as rows | ||
for _, line := range lines[1:] { | ||
values := strings.Split(line, "|") | ||
rowData := map[string]any{} | ||
for i, col := range columns { | ||
if i < len(values) { | ||
rowData[col] = values[i] | ||
} else { | ||
rowData[col] = nil | ||
} | ||
} | ||
output.Rows = append(output.Rows, rowData) | ||
} | ||
|
||
// Marshal the result to JSON | ||
content, err := json.Marshal(output) | ||
if err != nil { | ||
return "", fmt.Errorf("error marshalling output to JSON: %w", err) | ||
} | ||
|
||
return string(content), nil | ||
} |
Oops, something went wrong.