rosetta-sql 1.0.0__tar.gz → 1.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/PKG-INFO +9 -6
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/README.md +4 -4
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/pyproject.toml +2 -1
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/__init__.py +1 -1
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/config_cmd.py +29 -8
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/exec.py +22 -5
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/interactive_cmd.py +10 -18
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/list_cmd.py +5 -43
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/main.py +174 -77
- rosetta_sql-1.0.3/rosetta/cli/mtr_cmd.py +1160 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/output.py +169 -75
- rosetta_sql-1.0.3/rosetta/cli/result.py +101 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/result_cmd.py +22 -9
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/run.py +283 -192
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/status.py +3 -1
- rosetta_sql-1.0.3/rosetta/comparator.py +340 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/config.py +29 -18
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/executor.py +134 -6
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/interactive.py +341 -208
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/models.py +5 -16
- rosetta_sql-1.0.3/rosetta/mtr/__init__.py +42 -0
- rosetta_sql-1.0.3/rosetta/mtr/adapter.py +299 -0
- rosetta_sql-1.0.3/rosetta/mtr/connection.py +284 -0
- rosetta_sql-1.0.3/rosetta/mtr/error_handler.py +316 -0
- rosetta_sql-1.0.3/rosetta/mtr/executor.py +1070 -0
- rosetta_sql-1.0.3/rosetta/mtr/nodes.py +383 -0
- rosetta_sql-1.0.3/rosetta/mtr/parser.py +1158 -0
- rosetta_sql-1.0.3/rosetta/mtr/result_processor.py +384 -0
- rosetta_sql-1.0.3/rosetta/mtr/variable.py +335 -0
- rosetta_sql-1.0.3/rosetta/paths.py +53 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/reporter/bench_html.py +11 -3
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/reporter/history.py +230 -529
- rosetta_sql-1.0.3/rosetta/reporter/html.py +1136 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/reporter/text.py +13 -6
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/runner.py +522 -320
- rosetta_sql-1.0.3/rosetta/serve.py +65 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/ui.py +14 -27
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta_sql.egg-info/PKG-INFO +9 -6
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta_sql.egg-info/SOURCES.txt +12 -5
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta_sql.egg-info/requires.txt +3 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta_sql.egg-info/top_level.txt +1 -3
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/skills/rosetta/scripts/rosetta_wrapper.py +1 -1
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/tests/test_cli.py +19 -19
- rosetta_sql-1.0.0/benchmark/generate_csv_data.py +0 -83
- rosetta_sql-1.0.0/benchmark/import_data.py +0 -168
- rosetta_sql-1.0.0/rosetta/buglist.py +0 -108
- rosetta_sql-1.0.0/rosetta/cli/result.py +0 -61
- rosetta_sql-1.0.0/rosetta/comparator.py +0 -205
- rosetta_sql-1.0.0/rosetta/parser.py +0 -308
- rosetta_sql-1.0.0/rosetta/reporter/html.py +0 -644
- rosetta_sql-1.0.0/rosetta/whitelist.py +0 -161
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/LICENSE +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/__main__.py +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/benchmark.py +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/cli/__init__.py +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/flamegraph.py +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/reporter/__init__.py +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta/reporter/bench_text.py +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta_sql.egg-info/dependency_links.txt +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/rosetta_sql.egg-info/entry_points.txt +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/setup.cfg +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/setup.py +0 -0
- {rosetta_sql-1.0.0 → rosetta_sql-1.0.3}/skills/rosetta/scripts/install_rosetta.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: rosetta-sql
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Cross-DBMS SQL behavioral consistency verification tool
|
|
5
5
|
Author: yangshijie
|
|
6
6
|
License: MIT
|
|
@@ -27,6 +27,9 @@ Requires-Dist: rich>=13.0
|
|
|
27
27
|
Requires-Dist: prompt_toolkit>=3.0.52
|
|
28
28
|
Provides-Extra: mysql-connector
|
|
29
29
|
Requires-Dist: mysql-connector-python>=8.0; extra == "mysql-connector"
|
|
30
|
+
Provides-Extra: gcov
|
|
31
|
+
Requires-Dist: fastcov>=1.13; extra == "gcov"
|
|
32
|
+
Dynamic: license-file
|
|
30
33
|
|
|
31
34
|
# Rosetta
|
|
32
35
|
Cross-DBMS SQL testing & benchmarking toolkit.
|
|
@@ -86,7 +89,7 @@ curl -fsSL https://raw.githubusercontent.com/sjyango/rosetta/main/uninstall.sh |
|
|
|
86
89
|
rosetta config init
|
|
87
90
|
|
|
88
91
|
# 2. Edit DB connection info
|
|
89
|
-
vim
|
|
92
|
+
vim rosetta_config.json
|
|
90
93
|
|
|
91
94
|
# 3. Check DB connectivity
|
|
92
95
|
rosetta status
|
|
@@ -118,7 +121,7 @@ All commands support these flags (can appear before or after the subcommand):
|
|
|
118
121
|
| Argument | Default | Description |
|
|
119
122
|
|----------|---------|-------------|
|
|
120
123
|
| `-j / --json` | `False` | JSON output (AI Agent friendly) |
|
|
121
|
-
| `-c / --config` | `
|
|
124
|
+
| `-c / --config` | `rosetta_config.json` | DBMS config file path |
|
|
122
125
|
| `-v / --verbose` | `False` | Enable verbose/debug logging |
|
|
123
126
|
|
|
124
127
|
### Commands
|
|
@@ -272,7 +275,7 @@ rosetta config validate
|
|
|
272
275
|
|
|
273
276
|
| Action | Description |
|
|
274
277
|
|--------|-------------|
|
|
275
|
-
| `init` | Generate a sample `
|
|
278
|
+
| `init` | Generate a sample `rosetta_config.sample.json` |
|
|
276
279
|
| `show` | Display current config details |
|
|
277
280
|
| `validate` | Validate JSON structure and test connectivity |
|
|
278
281
|
|
|
@@ -340,7 +343,7 @@ rosetta i --serve
|
|
|
340
343
|
---
|
|
341
344
|
|
|
342
345
|
## Configuration
|
|
343
|
-
Sample `
|
|
346
|
+
Sample `rosetta_config.json`:
|
|
344
347
|
```json
|
|
345
348
|
{
|
|
346
349
|
"databases": [
|
|
@@ -56,7 +56,7 @@ curl -fsSL https://raw.githubusercontent.com/sjyango/rosetta/main/uninstall.sh |
|
|
|
56
56
|
rosetta config init
|
|
57
57
|
|
|
58
58
|
# 2. Edit DB connection info
|
|
59
|
-
vim
|
|
59
|
+
vim rosetta_config.json
|
|
60
60
|
|
|
61
61
|
# 3. Check DB connectivity
|
|
62
62
|
rosetta status
|
|
@@ -88,7 +88,7 @@ All commands support these flags (can appear before or after the subcommand):
|
|
|
88
88
|
| Argument | Default | Description |
|
|
89
89
|
|----------|---------|-------------|
|
|
90
90
|
| `-j / --json` | `False` | JSON output (AI Agent friendly) |
|
|
91
|
-
| `-c / --config` | `
|
|
91
|
+
| `-c / --config` | `rosetta_config.json` | DBMS config file path |
|
|
92
92
|
| `-v / --verbose` | `False` | Enable verbose/debug logging |
|
|
93
93
|
|
|
94
94
|
### Commands
|
|
@@ -242,7 +242,7 @@ rosetta config validate
|
|
|
242
242
|
|
|
243
243
|
| Action | Description |
|
|
244
244
|
|--------|-------------|
|
|
245
|
-
| `init` | Generate a sample `
|
|
245
|
+
| `init` | Generate a sample `rosetta_config.sample.json` |
|
|
246
246
|
| `show` | Display current config details |
|
|
247
247
|
| `validate` | Validate JSON structure and test connectivity |
|
|
248
248
|
|
|
@@ -310,7 +310,7 @@ rosetta i --serve
|
|
|
310
310
|
---
|
|
311
311
|
|
|
312
312
|
## Configuration
|
|
313
|
-
Sample `
|
|
313
|
+
Sample `rosetta_config.json`:
|
|
314
314
|
```json
|
|
315
315
|
{
|
|
316
316
|
"databases": [
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rosetta-sql"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.3"
|
|
8
8
|
description = "Cross-DBMS SQL behavioral consistency verification tool"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -34,6 +34,7 @@ dependencies = [
|
|
|
34
34
|
|
|
35
35
|
[project.optional-dependencies]
|
|
36
36
|
mysql-connector = ["mysql-connector-python>=8.0"]
|
|
37
|
+
gcov = ["fastcov>=1.13"]
|
|
37
38
|
|
|
38
39
|
[project.scripts]
|
|
39
40
|
rosetta = "rosetta.cli:main"
|
|
@@ -50,7 +50,9 @@ def _handle_config_show(args, output: "OutputFormatter") -> CommandResult:
|
|
|
50
50
|
|
|
51
51
|
if not os.path.isfile(args.config):
|
|
52
52
|
return CommandResult.failure(
|
|
53
|
-
f"Config file not found: {args.config}"
|
|
53
|
+
f"Config file not found: {args.config}\n"
|
|
54
|
+
f"Run 'rosetta config init' to create a sample config, "
|
|
55
|
+
f"or use '-c' to specify the config file path.",
|
|
54
56
|
)
|
|
55
57
|
|
|
56
58
|
try:
|
|
@@ -103,7 +105,9 @@ def _handle_config_validate(args, output: "OutputFormatter") -> CommandResult:
|
|
|
103
105
|
|
|
104
106
|
if not os.path.isfile(args.config):
|
|
105
107
|
return CommandResult.failure(
|
|
106
|
-
f"Config file not found: {args.config}"
|
|
108
|
+
f"Config file not found: {args.config}\n"
|
|
109
|
+
f"Run 'rosetta config init' to create a sample config, "
|
|
110
|
+
f"or use '-c' to specify the config file path.",
|
|
107
111
|
)
|
|
108
112
|
|
|
109
113
|
errors = []
|
|
@@ -204,7 +208,10 @@ def _handle_config_validate(args, output: "OutputFormatter") -> CommandResult:
|
|
|
204
208
|
|
|
205
209
|
def _handle_config_init(args, output: "OutputFormatter") -> CommandResult:
|
|
206
210
|
"""
|
|
207
|
-
|
|
211
|
+
Initialize ~/.rosetta directory and generate sample config.
|
|
212
|
+
|
|
213
|
+
Creates the ~/.rosetta/ directory structure and generates a sample
|
|
214
|
+
config.json if it doesn't already exist.
|
|
208
215
|
|
|
209
216
|
Args:
|
|
210
217
|
args: Parsed arguments
|
|
@@ -214,30 +221,44 @@ def _handle_config_init(args, output: "OutputFormatter") -> CommandResult:
|
|
|
214
221
|
CommandResult with generated config path
|
|
215
222
|
"""
|
|
216
223
|
from ..config import generate_sample_config
|
|
224
|
+
from ..paths import CONFIG_FILE, ensure_home
|
|
217
225
|
|
|
218
226
|
# Determine output path
|
|
219
|
-
output_path = args.output if args.output else
|
|
227
|
+
output_path = args.output if args.output else CONFIG_FILE
|
|
228
|
+
|
|
229
|
+
# Ensure ~/.rosetta directory exists
|
|
230
|
+
home = ensure_home()
|
|
220
231
|
|
|
221
232
|
# Check if file already exists
|
|
222
233
|
if os.path.isfile(output_path):
|
|
234
|
+
# Preserve the original command name: "init" when called via
|
|
235
|
+
# ``rosetta init``, "config init" when called via ``rosetta config init``
|
|
236
|
+
command = getattr(args, 'command', None)
|
|
237
|
+
cmd_name = "init" if command == "init" else "config init"
|
|
223
238
|
return CommandResult.failure(
|
|
224
|
-
f"
|
|
225
|
-
|
|
239
|
+
f"Config already exists: {output_path}. "
|
|
240
|
+
f"Edit it directly or use --output to specify a different path.",
|
|
241
|
+
command=cmd_name,
|
|
226
242
|
)
|
|
227
243
|
|
|
228
244
|
# Generate sample config
|
|
229
245
|
try:
|
|
230
246
|
generate_sample_config(output_path)
|
|
231
247
|
except Exception as e:
|
|
248
|
+
command = getattr(args, 'command', None)
|
|
249
|
+
cmd_name = "init" if command == "init" else "config init"
|
|
232
250
|
return CommandResult.failure(
|
|
233
251
|
f"Failed to generate config: {str(e)}",
|
|
234
|
-
command=
|
|
252
|
+
command=cmd_name,
|
|
235
253
|
)
|
|
236
254
|
|
|
237
255
|
return CommandResult.success(
|
|
238
256
|
"config init",
|
|
239
257
|
{
|
|
258
|
+
"rosetta_home": home,
|
|
240
259
|
"config_path": os.path.abspath(output_path),
|
|
241
|
-
"message": f"
|
|
260
|
+
"message": f"Initialized {home}\n"
|
|
261
|
+
f"Config written to {output_path}\n"
|
|
262
|
+
f"Edit the database connections, then run: rosetta status",
|
|
242
263
|
},
|
|
243
264
|
)
|
|
@@ -26,12 +26,15 @@ def handle_exec(args, output: "OutputFormatter") -> CommandResult:
|
|
|
26
26
|
import time as _time
|
|
27
27
|
from ..config import load_config, filter_configs
|
|
28
28
|
from ..executor import DBConnection, check_port
|
|
29
|
-
from ..parser import
|
|
29
|
+
from ..mtr.parser import MtrParser
|
|
30
|
+
from ..mtr.nodes import MtrCommandType
|
|
30
31
|
|
|
31
32
|
# Load config
|
|
32
33
|
if not os.path.isfile(args.config):
|
|
33
34
|
return CommandResult.failure(
|
|
34
|
-
f"Config file not found: {args.config}"
|
|
35
|
+
f"Config file not found: {args.config}\n"
|
|
36
|
+
f"Run 'rosetta config init' to create a sample config, "
|
|
37
|
+
f"or use '-c' to specify the config file path.",
|
|
35
38
|
)
|
|
36
39
|
|
|
37
40
|
all_configs = load_config(args.config)
|
|
@@ -65,13 +68,27 @@ def handle_exec(args, output: "OutputFormatter") -> CommandResult:
|
|
|
65
68
|
sql_text = f.read()
|
|
66
69
|
else:
|
|
67
70
|
return CommandResult.failure(
|
|
68
|
-
"Either --sql or --file is required"
|
|
71
|
+
"Either --sql or --file is required. "
|
|
72
|
+
"Use --sql 'SELECT ...' or --file /path/to/script.sql",
|
|
69
73
|
)
|
|
70
74
|
|
|
71
75
|
# Parse SQL statements
|
|
76
|
+
# For --sql mode, split on semicolons first so that
|
|
77
|
+
# "SELECT 1; SELECT 2" is treated as two statements.
|
|
78
|
+
# The MTR parser is line-based and won't split in-line semicolons.
|
|
72
79
|
try:
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
if args.sql and ";" in sql_text:
|
|
81
|
+
# Split by semicolons, filter empty, and re-join with newlines
|
|
82
|
+
# so the MTR parser treats each as a separate statement.
|
|
83
|
+
parts = [p.strip() for p in sql_text.split(";") if p.strip()]
|
|
84
|
+
sql_text_for_parse = ";\n".join(parts) + ";\n"
|
|
85
|
+
mtr_parser = MtrParser()
|
|
86
|
+
parsed = mtr_parser.parse_text(sql_text_for_parse)
|
|
87
|
+
else:
|
|
88
|
+
mtr_parser = MtrParser()
|
|
89
|
+
parsed = mtr_parser.parse_text(sql_text)
|
|
90
|
+
statements = [cmd.argument for cmd in parsed.commands
|
|
91
|
+
if cmd.cmd_type == MtrCommandType.SQL]
|
|
75
92
|
except Exception as e:
|
|
76
93
|
return CommandResult.failure(f"Parse error: {str(e)}")
|
|
77
94
|
|
|
@@ -31,7 +31,9 @@ def handle_interactive(args, output: "OutputFormatter") -> CommandResult:
|
|
|
31
31
|
# Load config
|
|
32
32
|
if not os.path.isfile(args.config):
|
|
33
33
|
return CommandResult.failure(
|
|
34
|
-
f"Config file not found: {args.config}"
|
|
34
|
+
f"Config file not found: {args.config}\n"
|
|
35
|
+
f"Run 'rosetta config init' to create a sample config, "
|
|
36
|
+
f"or use '-c' to specify the config file path.",
|
|
35
37
|
)
|
|
36
38
|
|
|
37
39
|
all_configs = load_config(args.config)
|
|
@@ -55,7 +57,7 @@ def handle_interactive(args, output: "OutputFormatter") -> CommandResult:
|
|
|
55
57
|
|
|
56
58
|
if not reachable_configs:
|
|
57
59
|
return CommandResult.failure(
|
|
58
|
-
"No reachable DBMS found. Check your
|
|
60
|
+
"No reachable DBMS found. Check your ~/.rosetta/config.json"
|
|
59
61
|
)
|
|
60
62
|
|
|
61
63
|
configs = reachable_configs
|
|
@@ -75,7 +77,7 @@ def handle_interactive(args, output: "OutputFormatter") -> CommandResult:
|
|
|
75
77
|
"dbms_targets": [c.name for c in configs],
|
|
76
78
|
"database": args.database,
|
|
77
79
|
"output_dir": os.path.abspath(args.output_dir),
|
|
78
|
-
"serve":
|
|
80
|
+
"serve": True,
|
|
79
81
|
"port": args.port,
|
|
80
82
|
},
|
|
81
83
|
)
|
|
@@ -95,29 +97,19 @@ def handle_interactive(args, output: "OutputFormatter") -> CommandResult:
|
|
|
95
97
|
|
|
96
98
|
# Use filtered configs (either user-specified or auto-detected reachable)
|
|
97
99
|
legacy_args.dbms = ",".join(c.name for c in configs)
|
|
98
|
-
if args.serve:
|
|
99
|
-
legacy_args.serve = args.serve
|
|
100
100
|
if args.port:
|
|
101
101
|
legacy_args.port = args.port
|
|
102
102
|
|
|
103
|
+
# serve is always on for interactive mode
|
|
104
|
+
legacy_args.serve = True
|
|
105
|
+
|
|
103
106
|
# Launch interactive session
|
|
104
107
|
exit_code = _enter_interactive(legacy_args)
|
|
105
108
|
|
|
106
|
-
return CommandResult.success(
|
|
107
|
-
"interactive",
|
|
108
|
-
{
|
|
109
|
-
"exit_code": exit_code,
|
|
110
|
-
"message": "Interactive session ended",
|
|
111
|
-
},
|
|
112
|
-
)
|
|
109
|
+
return CommandResult.success("interactive")
|
|
113
110
|
|
|
114
111
|
except KeyboardInterrupt:
|
|
115
|
-
return CommandResult.success(
|
|
116
|
-
"interactive",
|
|
117
|
-
{
|
|
118
|
-
"message": "Interactive session interrupted",
|
|
119
|
-
},
|
|
120
|
-
)
|
|
112
|
+
return CommandResult.success("interactive")
|
|
121
113
|
except Exception as e:
|
|
122
114
|
return CommandResult.failure(
|
|
123
115
|
f"Interactive session failed: {str(e)}",
|
|
@@ -26,8 +26,6 @@ def handle_list(args, output: "OutputFormatter") -> CommandResult:
|
|
|
26
26
|
return _handle_list_dbms(args, output)
|
|
27
27
|
elif args.resource == "history":
|
|
28
28
|
return _handle_list_history(args, output)
|
|
29
|
-
elif args.resource == "templates":
|
|
30
|
-
return _handle_list_templates(args, output)
|
|
31
29
|
else:
|
|
32
30
|
return CommandResult.failure(
|
|
33
31
|
f"Unknown list resource: {args.resource}",
|
|
@@ -51,7 +49,9 @@ def _handle_list_dbms(args, output: "OutputFormatter") -> CommandResult:
|
|
|
51
49
|
# Load config
|
|
52
50
|
if not os.path.isfile(args.config):
|
|
53
51
|
return CommandResult.failure(
|
|
54
|
-
f"Config file not found: {args.config}"
|
|
52
|
+
f"Config file not found: {args.config}\n"
|
|
53
|
+
f"Run 'rosetta config init' to create a sample config, "
|
|
54
|
+
f"or use '-c' to specify the config file path.",
|
|
55
55
|
)
|
|
56
56
|
|
|
57
57
|
all_configs = load_config(args.config)
|
|
@@ -107,7 +107,8 @@ def _handle_list_history(args, output: "OutputFormatter") -> CommandResult:
|
|
|
107
107
|
import json
|
|
108
108
|
from pathlib import Path
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
from ..paths import RESULTS_DIR as _DEFAULT_RESULTS
|
|
111
|
+
output_dir = args.output_dir if hasattr(args, "output_dir") else _DEFAULT_RESULTS
|
|
111
112
|
|
|
112
113
|
if not os.path.isdir(output_dir):
|
|
113
114
|
return CommandResult.failure(
|
|
@@ -173,43 +174,4 @@ def _handle_list_history(args, output: "OutputFormatter") -> CommandResult:
|
|
|
173
174
|
)
|
|
174
175
|
|
|
175
176
|
|
|
176
|
-
def _handle_list_templates(args, output: "OutputFormatter") -> CommandResult:
|
|
177
|
-
"""
|
|
178
|
-
List built-in benchmark templates.
|
|
179
|
-
|
|
180
|
-
Args:
|
|
181
|
-
args: Parsed arguments
|
|
182
|
-
output: Output formatter
|
|
183
|
-
|
|
184
|
-
Returns:
|
|
185
|
-
CommandResult with template list
|
|
186
|
-
"""
|
|
187
|
-
from ..benchmark import BenchmarkLoader
|
|
188
|
-
|
|
189
|
-
templates = BenchmarkLoader.list_builtin_templates()
|
|
190
|
-
|
|
191
|
-
template_info = []
|
|
192
|
-
for name in templates:
|
|
193
|
-
info = {
|
|
194
|
-
"name": name,
|
|
195
|
-
"description": _get_template_description(name),
|
|
196
|
-
}
|
|
197
|
-
template_info.append(info)
|
|
198
|
-
|
|
199
|
-
return CommandResult.success(
|
|
200
|
-
"list templates",
|
|
201
|
-
{
|
|
202
|
-
"total": len(templates),
|
|
203
|
-
"templates": template_info,
|
|
204
|
-
},
|
|
205
|
-
)
|
|
206
|
-
|
|
207
177
|
|
|
208
|
-
def _get_template_description(name: str) -> str:
|
|
209
|
-
"""Get description for a built-in template."""
|
|
210
|
-
descriptions = {
|
|
211
|
-
"oltp_read_write": "OLTP Read-Write mixed workload with point selects, updates, inserts, and aggregates",
|
|
212
|
-
"oltp_read_only": "OLTP Read-Only workload with point selects, range scans, and aggregates",
|
|
213
|
-
"oltp_write_only": "OLTP Write-Only workload with inserts, updates, replaces, and deletes",
|
|
214
|
-
}
|
|
215
|
-
return descriptions.get(name, "Built-in benchmark template")
|