packages/ztd-query-core/src/Simulator/StatementSimulator.php

1<?php
2
3declare(strict_types=1);
4
5namespace ZtdQuery\Simulator;
6
7use ZtdQuery\Connection\StatementInterface;
8use ZtdQuery\Rewrite\QueryKind;
9use ZtdQuery\Session;
10
11/**
12 * Executes rewritten statements and applies shadow mutations for exec().
13 *
14 * Exception handling for unsupported SQL and unknown schema is now done in Session::rewrite(),
15 * so this class simply delegates to the session.
16 */
17final class StatementSimulator
18{
19    /**
20     * Session context for rewrite and mutation application.
21     *
22     * @var Session
23     */
24    private Session $session;
25
26    /**
27     * @param Session $session Current ZTD session.
28     */
29    public function __construct(Session $session)
30    {
31        $this->session = $session;
32    }
33
34    /**
35     * Simulate exec() by running result-select and updating shadow state.
36     *
37     * Session::rewrite() now handles exceptions for unsupported SQL and unknown schema
38     * based on config, so we no longer need to handle FORBIDDEN/UNKNOWN_SCHEMA here.
39     *
40     * @param callable(string): (StatementInterface|false) $executor
41     */
42    public function simulate(string $statement, callable $executor): int|false
43    {
44        $plan = $this->session->rewrite($statement);
45
46        if ($plan->kind() === QueryKind::SKIPPED) {
47            return 0;
48        }
49
50        if ($plan->kind() === QueryKind::READ) {
51            $stmt = $executor($plan->sql());
52            if ($stmt === false) {
53                return false;
54            }
55            return $stmt->rowCount();
56        }
57
58        $rows = $this->session->runResultSelectAndApplyShadow($plan, $executor);
59
60        return count($rows);
61    }
62}
63