Skip to content

Commit d6d796b

Browse files
committed
refactor(cli): rename named-query to named-expression, add procedure-graph
Rename the CLI subcommand and underlying module from "named-query" to "named-expression" to reflect broader expression evaluation capability beyond just query execution. Add new "named-procedure-graph" subcommand for visualizing procedure relationship graphs. Update named_connection to pass output provider.
1 parent 5b05ec7 commit d6d796b

11 files changed

Lines changed: 469 additions & 72 deletions

File tree

‎docs/examples/chapter_12_named_procedure/diagram_demo.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
2. 执行过程后生成实例图
88
3. 将图嵌入文档
99
"""
10-
from rhosocial.activerecord.backend.named_query import (
10+
from rhosocial.activerecord.backend.named_expression import (
1111
Procedure,
1212
ProcedureContext,
1313
ProcedureRunner,

‎docs/examples/chapter_12_named_procedure/order_workflow.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
- 静态图和实例图生成
1010
- PostgreSQL 特有的 NOWAIT, RETURNING 等特性
1111
"""
12-
from rhosocial.activerecord.backend.named_query import (
12+
from rhosocial.activerecord.backend.named_expression import (
1313
Procedure,
1414
ProcedureContext,
1515
ParallelStep,
@@ -192,7 +192,7 @@ async def run(self, ctx: ProcedureContext) -> None:
192192

193193

194194
if __name__ == "__main__":
195-
from rhosocial.activerecord.backend.named_query import ProcedureDiagram
195+
from rhosocial.activerecord.backend.named_expression import ProcedureDiagram
196196

197197
print("=== 静态流程图 ===")
198198
print(OrderProcessingProcedure.static_diagram("flowchart"))

‎src/rhosocial/activerecord/backend/impl/postgres/cli/__init__.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
COMMAND_NAMES = [
77
'info', 'query', 'introspect', 'status',
8-
'named-query', 'named-procedure', 'named-connection',
8+
'named-expression', 'named-procedure', 'named-procedure-graph', 'named-connection',
99
]
1010

1111

@@ -15,15 +15,17 @@ def register_commands(subparsers):
1515
from .query import create_parser as query_parser
1616
from .introspect import create_parser as introspect_parser
1717
from .status import create_parser as status_parser
18-
from .named_query import create_parser as nq_parser
18+
from .named_expression import create_parser as nq_parser
1919
from .named_procedure import create_parser as np_parser
20+
from .named_procedure_graph import create_parser as npg_parser
2021
from .named_connection import create_parser as nc_parser
2122
info_parser(subparsers)
2223
query_parser(subparsers)
2324
introspect_parser(subparsers)
2425
status_parser(subparsers)
2526
nq_parser(subparsers)
2627
np_parser(subparsers)
28+
npg_parser(subparsers)
2729
nc_parser(subparsers)
2830

2931

‎src/rhosocial/activerecord/backend/impl/postgres/cli/connection.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def add_version_arg(parser):
7070
def create_connection_parent_parser():
7171
"""Create a parent parser with connection and output arguments.
7272
73-
Used by shared CLI helpers (named-query, named-procedure) that
73+
Used by shared CLI helpers (named-expression, named-procedure) that
7474
require a parent_parser containing connection parameters.
7575
"""
7676
import argparse

‎src/rhosocial/activerecord/backend/impl/postgres/cli/named_connection.py‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,12 @@ def handle(args):
2626
"""Handle the named-connection subcommand."""
2727
from rhosocial.activerecord.backend.named_connection.cli import handle_named_connection as handle_nc
2828

29+
from .output import create_provider
30+
output_fmt = getattr(args, "output", "table")
31+
ascii_borders = getattr(args, "rich_ascii", False)
32+
provider = create_provider(output_fmt, ascii_borders=ascii_borders)
33+
2934
def named_connection_resolver_factory(name):
3035
return NamedConnectionResolver(name)
3136

32-
handle_nc(args, named_connection_resolver_factory)
37+
handle_nc(args, named_connection_resolver_factory, provider)

src/rhosocial/activerecord/backend/impl/postgres/cli/named_query.py renamed to src/rhosocial/activerecord/backend/impl/postgres/cli/named_expression.py

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# src/rhosocial/activerecord/backend/impl/postgres/cli/named_query.py
2-
"""named-query subcommand - Adapter for shared CLI helper.
1+
# src/rhosocial/activerecord/backend/impl/postgres/cli/named_expression.py
2+
"""named-expression subcommand - Adapter for shared CLI helper.
33
4-
named-query requires connection arguments and output arguments.
4+
named-expression requires connection arguments and output arguments.
55
"""
66

77
from rhosocial.activerecord.backend.impl.postgres import PostgresBackend, AsyncPostgresBackend
@@ -12,44 +12,38 @@
1212

1313

1414
def create_parser(subparsers):
15-
"""Create the named-query subcommand parser.
15+
"""Create the named-expression subcommand parser.
1616
17-
Reuses the shared create_named_query_parser, passing a parent parser
17+
Reuses the shared create_named_expression_parser, passing a parent parser
1818
containing only connection and output arguments.
1919
"""
20-
from rhosocial.activerecord.backend.named_query.cli import create_named_query_parser
20+
from rhosocial.activerecord.backend.named_expression.cli import create_named_expression_parser
2121
local_parent = create_connection_parent_parser()
22+
parser = create_named_expression_parser(subparsers, local_parent)
23+
parser.add_argument(
24+
"--dialect-version",
25+
default=None,
26+
help="PostgreSQL dialect version for capability probing (e.g., 15.0.0, 14.0.0).",
27+
)
28+
return parser
2229

23-
nq_epilog = """Examples:
24-
# Execute named query with connection parameters
25-
%(prog)s myapp.queries.orders.high_value_pending --host localhost --database mydb --user postgres --password secret
26-
27-
# Override parameters
28-
%(prog)s myapp.queries.orders.high_value_pending --host localhost --database mydb \\
29-
--param threshold=5000 --param days=7
30-
31-
# Show signature without executing
32-
%(prog)s myapp.queries.orders.high_value_pending --describe
33-
34-
# Preview SQL without executing
35-
%(prog)s myapp.queries.orders.orders_by_status \\
36-
--database mydb --param status=pending --dry-run
3730

38-
# List all named queries in a module
39-
%(prog)s myapp.queries.orders --list
31+
def handle(args):
32+
"""Handle the named-expression subcommand."""
33+
from rhosocial.activerecord.backend.named_expression.cli import handle_named_expression as handle_ne
4034

41-
# Using environment variables
42-
export POSTGRES_HOST=localhost POSTGRES_DATABASE=mydb POSTGRES_USER=postgres POSTGRES_PASSWORD=secret
43-
%(prog)s myapp.queries.orders --list
44-
"""
45-
return create_named_query_parser(subparsers, local_parent, epilog=nq_epilog)
35+
provider = create_provider(args.output, ascii_borders=args.rich_ascii)
4636

37+
from rhosocial.activerecord.backend.impl.postgres.dialect import PostgresDialect
4738

48-
def handle(args):
49-
"""Handle the named-query subcommand."""
50-
from rhosocial.activerecord.backend.named_query.cli import handle_named_query as handle_nq
39+
def _get_requested_version():
40+
ver = getattr(args, "dialect_version", None)
41+
if ver:
42+
return tuple(int(p) for p in ver.split("."))
43+
return None
5144

52-
provider = create_provider(args.output, ascii_borders=args.rich_ascii)
45+
def create_dialect():
46+
return PostgresDialect(version=_get_requested_version())
5347

5448
backend = None
5549

@@ -59,6 +53,9 @@ def backend_factory():
5953
backend = PostgresBackend(connection_config=config)
6054
backend.connect()
6155
backend.introspect_and_adapt()
56+
req_ver = _get_requested_version()
57+
if req_ver:
58+
backend._dialect.version = req_ver
6259
return backend
6360

6461
def get_dialect(b):
@@ -91,7 +88,7 @@ async def disconnect_async():
9188
if async_backend and async_backend._connection:
9289
await async_backend.disconnect()
9390

94-
handle_nq(
91+
handle_ne(
9592
args,
9693
provider,
9794
backend_factory=backend_factory,
@@ -102,14 +99,16 @@ async def disconnect_async():
10299
get_dialect_async=get_dialect_async,
103100
execute_query_async=execute_query_async,
104101
disconnect_async=disconnect_async,
102+
create_dialect=create_dialect,
105103
)
106104
return
107105

108-
handle_nq(
106+
handle_ne(
109107
args,
110108
provider,
111109
backend_factory=backend_factory,
112110
get_dialect=get_dialect,
113111
execute_query=execute_query,
114112
disconnect=disconnect,
113+
create_dialect=create_dialect,
115114
)

‎src/rhosocial/activerecord/backend/impl/postgres/cli/named_procedure.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def create_parser(subparsers):
1616
Reuses the shared create_named_procedure_parser, passing a parent parser
1717
containing only connection and output arguments.
1818
"""
19-
from rhosocial.activerecord.backend.named_query.cli_procedure import create_named_procedure_parser
19+
from rhosocial.activerecord.backend.named_expression.cli_procedure import create_named_procedure_parser
2020
local_parent = create_connection_parent_parser()
2121

2222
np_epilog = """Examples:
@@ -43,7 +43,7 @@ def create_parser(subparsers):
4343

4444
def handle(args):
4545
"""Handle the named-procedure subcommand."""
46-
from rhosocial.activerecord.backend.named_query.cli_procedure import handle_named_procedure as handle_np
46+
from rhosocial.activerecord.backend.named_expression.cli_procedure import handle_named_procedure as handle_np
4747

4848
provider = create_provider(args.output, ascii_borders=args.rich_ascii)
4949

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# src/rhosocial/activerecord/backend/impl/postgres/cli/named_procedure_graph.py
2+
"""named-procedure-graph subcommand - Adapter for shared CLI helper.
3+
4+
named-procedure-graph requires connection arguments, output arguments, and --rich-ascii.
5+
6+
Usage:
7+
$ python -m rhosocial.activerecord.backend.impl.postgres named-procedure-graph run \
8+
myapp.npg.monthly_report \
9+
--params '{"month": "2026-04"}'
10+
11+
$ python -m rhosocial.activerecord.backend.impl.postgres named-procedure-graph list \
12+
myapp.npg
13+
14+
$ python -m rhosocial.activerecord.backend.impl.postgres named-procedure-graph validate \
15+
myapp.npg.monthly_report
16+
"""
17+
18+
from rhosocial.activerecord.backend.impl.postgres import PostgresBackend
19+
20+
from .connection import create_connection_parent_parser, resolve_connection_config_from_args
21+
from .output import create_provider
22+
23+
24+
def create_parser(subparsers):
25+
"""Create the named-procedure-graph subcommand parser.
26+
27+
Reuses the shared create_named_procedure_graph_parser, passing a parent parser
28+
containing only connection and output arguments.
29+
"""
30+
from rhosocial.activerecord.backend.named_expression.cli_procedure_graph import (
31+
create_named_procedure_graph_parser,
32+
)
33+
34+
local_parent = create_connection_parent_parser()
35+
return create_named_procedure_graph_parser(subparsers, local_parent)
36+
37+
38+
def handle(args):
39+
"""Handle the named-procedure-graph subcommand."""
40+
from rhosocial.activerecord.backend.named_expression.cli_procedure_graph import (
41+
handle_named_procedure_graph as handle_npg,
42+
)
43+
44+
provider = create_provider(args.output, ascii_borders=args.rich_ascii)
45+
46+
backend = None
47+
48+
def backend_factory():
49+
nonlocal backend
50+
config = resolve_connection_config_from_args(args)
51+
backend = PostgresBackend(connection_config=config)
52+
backend.connect()
53+
backend.introspect_and_adapt()
54+
return backend
55+
56+
def disconnect():
57+
if backend and backend._connection:
58+
backend.disconnect()
59+
60+
is_async = getattr(args, "is_async", False)
61+
62+
if is_async:
63+
async_backend = None
64+
65+
def backend_async_factory():
66+
nonlocal async_backend
67+
from rhosocial.activerecord.backend.impl.postgres import AsyncPostgresBackend
68+
69+
config = resolve_connection_config_from_args(args)
70+
async_backend = AsyncPostgresBackend(connection_config=config)
71+
return async_backend
72+
73+
async def disconnect_async():
74+
if async_backend and async_backend._connection:
75+
await async_backend.disconnect()
76+
77+
handle_npg(
78+
args,
79+
provider,
80+
backend_factory=backend_factory,
81+
disconnect=disconnect,
82+
backend_async_factory=backend_async_factory,
83+
disconnect_async=disconnect_async,
84+
)
85+
return
86+
87+
handle_npg(
88+
args,
89+
provider,
90+
backend_factory=backend_factory,
91+
disconnect=disconnect,
92+
)

0 commit comments

Comments
 (0)