dbagent-cli 0.1.6__tar.gz → 0.1.8__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.
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/PKG-INFO +1 -1
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/__init__.py +1 -1
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/cli.py +183 -92
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/connectors/relational.py +10 -7
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent_cli.egg-info/PKG-INFO +1 -1
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/pyproject.toml +1 -1
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/README.md +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/agent/generator.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/agent/pipeline.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/agent/validator.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/config.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/connectors/base.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/connectors/factory.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/connectors/mongo.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/llm/auto_setup.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/llm/base.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/llm/factory.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/llm/gemini_provider.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/llm/groq_provider.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/llm/mock_provider.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/llm/ollama_provider.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/llm/openrouter_provider.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/schema/formatter.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/schema/models.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/schema/selector.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/ui/console.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent/ui/viewer.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent_cli.egg-info/SOURCES.txt +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent_cli.egg-info/dependency_links.txt +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent_cli.egg-info/entry_points.txt +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent_cli.egg-info/requires.txt +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/dbagent_cli.egg-info/top_level.txt +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/setup.cfg +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/tests/test_cli.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/tests/test_connectors.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/tests/test_generator.py +0 -0
- {dbagent_cli-0.1.6 → dbagent_cli-0.1.8}/tests/test_schema.py +0 -0
|
@@ -509,7 +509,7 @@ def chat_command(
|
|
|
509
509
|
console.print(f"[bold green]Connected:[/bold green] {db_name} ({dialect}) - {len(table_names)} tables")
|
|
510
510
|
console.print(f"[bold cyan]AI:[/bold cyan] {llm.name}")
|
|
511
511
|
console.print("[dim]Type your question in plain English. Read queries auto-execute. Write queries ask for confirmation.[/dim]")
|
|
512
|
-
console.print("[dim]Commands: [bold]:tables[/bold] | [bold]:table <name>[/bold] | [bold]:fk <name>[/bold] | [bold]:explain[/bold] | [bold]:history[/bold] | [bold]:auto[/bold]/[bold]:noauto[/bold] | [bold]:run[/bold] | [bold]:export <file>[/bold] | [bold]:exit[/bold][/dim]\n")
|
|
512
|
+
console.print("[dim]Commands: [bold]:tables[/bold] | [bold]:table <name>[/bold] | [bold]:fk <name>[/bold] | [bold]:model <name>[/bold] | [bold]:explain[/bold] | [bold]:history[/bold] | [bold]:auto[/bold]/[bold]:noauto[/bold] | [bold]:run[/bold] | [bold]:export <file>[/bold] | [bold]:exit[/bold][/dim]\n")
|
|
513
513
|
|
|
514
514
|
history_file = config_mgr.config_dir / "chat_history.txt"
|
|
515
515
|
session = PromptSession(history=FileHistory(str(history_file)))
|
|
@@ -524,108 +524,180 @@ def chat_command(
|
|
|
524
524
|
if not user_input:
|
|
525
525
|
continue
|
|
526
526
|
|
|
527
|
-
# --- REPL commands ---
|
|
528
|
-
if user_input.
|
|
529
|
-
|
|
530
|
-
|
|
527
|
+
# --- REPL commands (all start with :) ---
|
|
528
|
+
if user_input.startswith(":"):
|
|
529
|
+
cmd_parts = user_input.split(maxsplit=1)
|
|
530
|
+
cmd_name = cmd_parts[0].lower()
|
|
531
|
+
cmd_arg = cmd_parts[1].strip() if len(cmd_parts) > 1 else ""
|
|
532
|
+
|
|
533
|
+
if cmd_name in [":exit", ":quit", ":q"]:
|
|
534
|
+
console.print("[bold cyan]Goodbye![/bold cyan]")
|
|
535
|
+
break
|
|
536
|
+
|
|
537
|
+
if cmd_name in [":help", ":h", ":?"]:
|
|
538
|
+
console.print("\n[bold cyan]Interactive Chat Commands:[/bold cyan]")
|
|
539
|
+
console.print(" [bold]:tables[/bold] -> List all tables in this database")
|
|
540
|
+
console.print(" [bold]:table <name>[/bold] -> Inspect columns, PKs, types & sample data")
|
|
541
|
+
console.print(" [bold]:fk <name>[/bold] -> View mapped foreign keys & related tables")
|
|
542
|
+
console.print(" [bold]:provider <name>[/bold] -> Switch AI provider (ollama, gemini, groq, openrouter)")
|
|
543
|
+
console.print(" [bold]:model <name>[/bold] -> Switch active model name (e.g. gemini-3.6-flash)")
|
|
544
|
+
console.print(" [bold]:models[/bold] -> Show active AI provider and model status")
|
|
545
|
+
console.print(" [bold]:explain[/bold] -> Show generated SQL & query analysis for last turn")
|
|
546
|
+
console.print(" [bold]:history[/bold] -> View history of queries in this session")
|
|
547
|
+
console.print(" [bold]:auto[/bold] / [bold]:noauto[/bold] -> Toggle automatic execution of read queries")
|
|
548
|
+
console.print(" [bold]:run[/bold] -> Re-execute the last generated SQL query")
|
|
549
|
+
console.print(" [bold]:export <file>[/bold] -> Save the last generated SQL to a file")
|
|
550
|
+
console.print(" [bold]:exit[/bold] -> Exit chat session\n")
|
|
551
|
+
continue
|
|
531
552
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
553
|
+
if cmd_name in [":tables", ":schema", ":dt"]:
|
|
554
|
+
with console.status("[bold cyan]Fetching schema...[/bold cyan]"):
|
|
555
|
+
schema = connector.inspect_schema(include_samples=False, max_samples=0, include_row_counts=False)
|
|
556
|
+
SchemaViewer.display_schema_summary(schema)
|
|
557
|
+
continue
|
|
537
558
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
559
|
+
if cmd_name == ":table":
|
|
560
|
+
if not cmd_arg:
|
|
561
|
+
print_warning("Usage: :table <table_name> (e.g. :table ivis_users)")
|
|
562
|
+
continue
|
|
563
|
+
exact, fuzzy = connector.resolve_tables(cmd_arg)
|
|
564
|
+
target = exact[0] if exact else (fuzzy[0] if fuzzy else cmd_arg)
|
|
565
|
+
with console.status(f"[bold cyan]Inspecting {target}...[/bold cyan]"):
|
|
566
|
+
on_demand_schema = connector.inspect_schema(table_names=[target], include_samples=True)
|
|
567
|
+
tmodel = on_demand_schema.get_table(target)
|
|
568
|
+
if tmodel:
|
|
569
|
+
SchemaViewer.display_table_detail(tmodel)
|
|
570
|
+
else:
|
|
571
|
+
print_error(f"Table '{cmd_arg}' not found.")
|
|
572
|
+
continue
|
|
550
573
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
for
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
574
|
+
if cmd_name in [":fk", ":relations", ":mapped"]:
|
|
575
|
+
if not cmd_arg:
|
|
576
|
+
print_warning("Usage: :fk <table_name> (e.g. :fk ivis_users)")
|
|
577
|
+
continue
|
|
578
|
+
exact, fuzzy = connector.resolve_tables(cmd_arg)
|
|
579
|
+
target = exact[0] if exact else (fuzzy[0] if fuzzy else cmd_arg)
|
|
580
|
+
with console.status(f"[bold cyan]Finding relationships for {target}...[/bold cyan]"):
|
|
581
|
+
full_schema = connector.inspect_schema(include_samples=False, max_samples=0)
|
|
582
|
+
|
|
583
|
+
tmodel = full_schema.get_table(target)
|
|
584
|
+
outgoing = tmodel.foreign_keys if tmodel else []
|
|
585
|
+
incoming = []
|
|
586
|
+
for other in full_schema.tables:
|
|
587
|
+
for fk in other.foreign_keys:
|
|
588
|
+
if fk.referred_table.lower() == target.lower():
|
|
589
|
+
incoming.append((other.name, fk))
|
|
590
|
+
|
|
591
|
+
console.print(f"\n[bold cyan]Relationships mapped to table: [bold white]{target}[/bold white][/bold cyan]\n")
|
|
592
|
+
if outgoing:
|
|
593
|
+
console.print("[bold green]Outgoing (This table references):[/bold green]")
|
|
594
|
+
for fk in outgoing:
|
|
595
|
+
console.print(f" * ({', '.join(fk.constrained_columns)}) -> [bold]{fk.referred_table}[/bold]({', '.join(fk.referred_columns)})")
|
|
596
|
+
if incoming:
|
|
597
|
+
console.print("\n[bold yellow]Incoming (Other tables reference this table):[/bold yellow]")
|
|
598
|
+
for src_table, fk in incoming:
|
|
599
|
+
console.print(f" * [bold]{src_table}[/bold]({', '.join(fk.constrained_columns)}) -> ({', '.join(fk.referred_columns)})")
|
|
600
|
+
if not outgoing and not incoming:
|
|
601
|
+
console.print(f"[dim]No foreign key constraints found directly mapped to '{target}'.[/dim]")
|
|
602
|
+
console.print("")
|
|
603
|
+
continue
|
|
580
604
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
605
|
+
if cmd_name in [":provider", ":use"]:
|
|
606
|
+
if not cmd_arg:
|
|
607
|
+
curr_model = model or getattr(llm, "default_model", "default")
|
|
608
|
+
console.print(f"\n[bold cyan]Active AI Provider:[/bold cyan] [bold white]{llm.name}[/bold white] | Model: [bold green]{curr_model}[/bold green]")
|
|
609
|
+
console.print("[dim]Usage: [bold]:provider <ollama|gemini|groq|openrouter>[/bold][/dim]\n")
|
|
610
|
+
continue
|
|
611
|
+
prov_target = cmd_arg.lower()
|
|
612
|
+
if prov_target in ["ollama", "gemini", "groq", "openrouter", "mock"]:
|
|
613
|
+
llm = get_llm_provider(provider_name=prov_target, config_mgr=config_mgr)
|
|
614
|
+
model = None
|
|
615
|
+
print_success(f"Switched AI provider to [bold cyan]{llm.name}[/bold cyan]")
|
|
616
|
+
else:
|
|
617
|
+
print_error(f"Unknown provider '{cmd_arg}'. Supported: ollama, gemini, groq, openrouter")
|
|
618
|
+
continue
|
|
592
619
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
620
|
+
if cmd_name == ":model":
|
|
621
|
+
if not cmd_arg:
|
|
622
|
+
curr_model = model or getattr(llm, "default_model", "default")
|
|
623
|
+
console.print(f"Active Model: [bold green]{curr_model}[/bold green] (Provider: {llm.name})")
|
|
624
|
+
console.print("[dim]Usage: [bold]:model <model_name>[/bold][/dim]")
|
|
625
|
+
continue
|
|
626
|
+
model = cmd_arg
|
|
627
|
+
print_success(f"Switched active model to [bold cyan]{model}[/bold cyan] (Provider: {llm.name})")
|
|
596
628
|
continue
|
|
597
|
-
for i, r in enumerate(query_history[-10:], 1):
|
|
598
|
-
status = "[green]OK[/green]" if r.success else "[red]FAIL[/red]"
|
|
599
|
-
sql_preview = (r.sql[:80] + "...") if len(r.sql) > 80 else r.sql
|
|
600
|
-
console.print(f" {i}. {status} [{r.query_type}] {sql_preview}")
|
|
601
|
-
continue
|
|
602
629
|
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
630
|
+
if cmd_name in [":models", ":providers", ":ai"]:
|
|
631
|
+
curr_model = model or getattr(llm, "default_model", "default")
|
|
632
|
+
console.print(f"\n[bold cyan]Active AI Provider:[/bold cyan] [bold white]{llm.name}[/bold white]")
|
|
633
|
+
console.print(f"[bold cyan]Active Model:[/bold cyan] [bold green]{curr_model}[/bold green]")
|
|
634
|
+
console.print("[dim]Switch anytime: [bold]:provider <ollama|gemini|groq|openrouter>[/bold] or [bold]:model <name>[/bold][/dim]\n")
|
|
635
|
+
continue
|
|
607
636
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
637
|
+
if cmd_name == ":explain":
|
|
638
|
+
if last_result and last_result.sql:
|
|
639
|
+
print_code(last_result.sql, "sql", "Last Executed SQL")
|
|
640
|
+
console.print(f"[dim]Query type: {last_result.query_type} | Intent: {last_result.intent} | Retries: {last_result.retries}[/dim]")
|
|
641
|
+
if last_result.exact_tables:
|
|
642
|
+
console.print(f"[dim]Tables (exact): {', '.join(last_result.exact_tables)}[/dim]")
|
|
643
|
+
if last_result.fuzzy_tables:
|
|
644
|
+
console.print(f"[dim]Tables (fuzzy): {', '.join(last_result.fuzzy_tables)}[/dim]")
|
|
645
|
+
else:
|
|
646
|
+
print_warning("No previous query to explain.")
|
|
647
|
+
continue
|
|
612
648
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
649
|
+
if cmd_name == ":history":
|
|
650
|
+
if not query_history:
|
|
651
|
+
print_warning("No query history in this session.")
|
|
652
|
+
continue
|
|
653
|
+
for i, r in enumerate(query_history[-10:], 1):
|
|
654
|
+
status = "[green]OK[/green]" if r.success else "[red]FAIL[/red]"
|
|
655
|
+
sql_preview = (r.sql[:80] + "...") if len(r.sql) > 80 else r.sql
|
|
656
|
+
console.print(f" {i}. {status} [{r.query_type}] {sql_preview}")
|
|
657
|
+
continue
|
|
658
|
+
|
|
659
|
+
if cmd_name == ":auto":
|
|
660
|
+
auto_execute = True
|
|
661
|
+
print_success("Auto-execute enabled. Read queries will run automatically.")
|
|
662
|
+
continue
|
|
663
|
+
|
|
664
|
+
if cmd_name == ":noauto":
|
|
665
|
+
auto_execute = False
|
|
666
|
+
print_info("Auto-execute disabled. All queries will show SQL only. Use :run to execute.")
|
|
667
|
+
continue
|
|
668
|
+
|
|
669
|
+
if cmd_name == ":run":
|
|
670
|
+
if not last_result or not last_result.sql:
|
|
671
|
+
print_warning("No generated SQL query to run.")
|
|
672
|
+
continue
|
|
673
|
+
if last_result.was_executed:
|
|
674
|
+
console.print("[dim]Re-executing last query...[/dim]")
|
|
675
|
+
cols, rows, err = connector.execute_query(last_result.sql, limit=100)
|
|
676
|
+
if err:
|
|
677
|
+
print_error(f"Execution error: {err}")
|
|
678
|
+
else:
|
|
679
|
+
print_results_table(cols, rows)
|
|
680
|
+
continue
|
|
681
|
+
|
|
682
|
+
if cmd_name == ":export":
|
|
683
|
+
if not cmd_arg:
|
|
684
|
+
print_warning("Usage: :export <file_path> (e.g. :export query.sql)")
|
|
685
|
+
continue
|
|
686
|
+
if not last_result or not last_result.sql:
|
|
687
|
+
print_warning("No code block to export.")
|
|
688
|
+
continue
|
|
689
|
+
p = Path(cmd_arg)
|
|
690
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
691
|
+
p.write_text(last_result.sql, encoding="utf-8")
|
|
692
|
+
print_success(f"SQL saved to {p}")
|
|
616
693
|
continue
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
console.print("[dim]Re-executing last query...[/dim]")
|
|
620
|
-
cols, rows, err = connector.execute_query(last_result.sql, limit=100)
|
|
621
|
-
if err:
|
|
622
|
-
print_error(f"Execution error: {err}")
|
|
623
|
-
else:
|
|
624
|
-
print_results_table(cols, rows)
|
|
694
|
+
|
|
695
|
+
print_warning(f"Unknown command '{user_input}'. Type [bold]:help[/bold] to see all in-chat commands.")
|
|
625
696
|
continue
|
|
626
697
|
|
|
627
|
-
if user_input.
|
|
628
|
-
|
|
698
|
+
if user_input.lower() in ["exit", "quit", "q"]:
|
|
699
|
+
console.print("[bold cyan]Goodbye![/bold cyan]")
|
|
700
|
+
break
|
|
629
701
|
if not last_result or not last_result.sql:
|
|
630
702
|
print_warning("No code block to export.")
|
|
631
703
|
continue
|
|
@@ -782,7 +854,7 @@ def models_command():
|
|
|
782
854
|
gemini = get_llm_provider("gemini")
|
|
783
855
|
gemini_status = "[green]Configured[/green]" if gemini.is_available() else "[yellow]Not Configured (Free Key: aistudio.google.com)[/yellow]"
|
|
784
856
|
console.print(f"\n2. [bold white]Google Gemini (Free Tier)[/bold white] - Status: {gemini_status}")
|
|
785
|
-
console.print(" Available Models: `gemini-
|
|
857
|
+
console.print(" Available Models: `gemini-3.6-flash`, `gemini-2.5-flash`, `gemini-2.5-pro`")
|
|
786
858
|
|
|
787
859
|
groq = get_llm_provider("groq")
|
|
788
860
|
groq_status = "[green]Configured[/green]" if groq.is_available() else "[yellow]Not Configured (Free Key: console.groq.com)[/yellow]"
|
|
@@ -922,5 +994,24 @@ def setup_command(
|
|
|
922
994
|
console.print(" * [bold]db-agent guide[/bold] -> View full command reference\n")
|
|
923
995
|
|
|
924
996
|
|
|
997
|
+
# ---- use ----
|
|
998
|
+
|
|
999
|
+
@app.command(name="use")
|
|
1000
|
+
def use_command(
|
|
1001
|
+
provider_name: str = typer.Argument(..., help="AI provider name (ollama, gemini, groq, openrouter)"),
|
|
1002
|
+
model: Optional[str] = typer.Option(None, "--model", "-m", help="Optional default model name"),
|
|
1003
|
+
):
|
|
1004
|
+
"""Switch the default AI provider (e.g. `db-agent use gemini` or `db-agent use ollama`)."""
|
|
1005
|
+
p = provider_name.lower()
|
|
1006
|
+
if p not in ["ollama", "gemini", "groq", "openrouter", "mock"]:
|
|
1007
|
+
print_error(f"Invalid provider '{provider_name}'. Supported: ollama, gemini, groq, openrouter")
|
|
1008
|
+
raise typer.Exit(1)
|
|
1009
|
+
|
|
1010
|
+
config_mgr.set_setting("default_provider", p)
|
|
1011
|
+
if model:
|
|
1012
|
+
config_mgr.set_setting(f"{p}_default_model", model)
|
|
1013
|
+
print_success(f"Default AI provider switched to [bold cyan]{p}[/bold cyan]!")
|
|
1014
|
+
|
|
1015
|
+
|
|
925
1016
|
if __name__ == "__main__":
|
|
926
1017
|
app()
|
|
@@ -447,19 +447,22 @@ class RelationalConnector(BaseConnector):
|
|
|
447
447
|
limit: int = 100,
|
|
448
448
|
) -> Tuple[List[str], List[Dict[str, Any]], Optional[str]]:
|
|
449
449
|
"""Safely execute a query with row limit."""
|
|
450
|
+
clean_q = query.strip()
|
|
450
451
|
try:
|
|
451
452
|
with self.engine.connect() as conn:
|
|
452
453
|
try:
|
|
453
|
-
|
|
454
|
+
conn = conn.execution_options(isolation_level="AUTOCOMMIT")
|
|
454
455
|
except Exception:
|
|
455
|
-
|
|
456
|
+
pass
|
|
457
|
+
|
|
458
|
+
try:
|
|
459
|
+
result = conn.exec_driver_sql(clean_q)
|
|
460
|
+
except Exception:
|
|
461
|
+
result = conn.execute(text(clean_q))
|
|
462
|
+
|
|
456
463
|
if not result.returns_rows:
|
|
457
|
-
# DML: commit and report affected rows
|
|
458
|
-
try:
|
|
459
|
-
conn.commit()
|
|
460
|
-
except Exception:
|
|
461
|
-
pass
|
|
462
464
|
return ["status"], [{"status": "Query executed successfully."}], None
|
|
465
|
+
|
|
463
466
|
columns = list(result.keys())
|
|
464
467
|
raw_rows = result.fetchmany(limit)
|
|
465
468
|
rows = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|