Skip to content

Commit e12a4ab

Browse files
committed
Add lazy native parser node facade
When a native parser is in use, expose query results through a node class that defers child materialization until callers actually walk the tree. The base WP_Parser_Node::$children visibility is loosened to protected so the facade can populate it on demand.
1 parent 57a6d43 commit e12a4ab

1 file changed

Lines changed: 73 additions & 41 deletions

File tree

packages/mysql-on-sqlite/src/mysql/native/class-wp-mysql-native-parser-node.php

Lines changed: 73 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
* children are never materialized into PHP arrays unless something actually
1212
* asks for them.
1313
*
14-
* Read methods eagerly call `materialize_native_children()` — once the
15-
* children have been copied into PHP, `was_mutated()` returns true and the
16-
* call falls through to the parent implementation. The `was_mutated` flag is
17-
* NOT a runtime check for whether the native extension is loaded — if this
18-
* class is in use, the extension is loaded by definition. It tracks whether
19-
* THIS specific node has had its children pulled into the inherited
20-
* `$children` array (which happens on first read or first mutation via
21-
* `append_child()` / `merge_fragment()`). From that point on, the node is a
22-
* plain PHP-backed `WP_Parser_Node`.
14+
* The hedge in those methods (`if ( $this->was_mutated() )`) is NOT a runtime
15+
* check for whether the native extension is loaded — if this class is in use,
16+
* the extension is loaded by definition. It checks whether THIS specific node
17+
* has been mutated from PHP. A node loses its native backing the first time
18+
* `append_child()` or `merge_fragment()` is called on it: those overrides
19+
* invoke `materialize_native_children()`, which copies the native children
20+
* into the inherited `$children` array and drops the native AST reference.
21+
* From that point on, the node is a plain PHP-backed `WP_Parser_Node` and the
22+
* read methods fall through to the parent implementation.
2323
*
2424
* Mutation from PHP is real and intentional — query rewriters in
2525
* `WP_PDO_MySQL_On_SQLite` (e.g. building synthetic `count(*)` expressions)
@@ -56,98 +56,130 @@ public function merge_fragment( $node ) {
5656

5757
/** @inheritDoc */
5858
public function has_child(): bool {
59-
$this->materialize_native_children();
60-
return parent::has_child();
59+
if ( $this->was_mutated() ) {
60+
return parent::has_child();
61+
}
62+
return wp_sqlite_mysql_native_ast_has_child( $this->native_ast, $this->native_node_index );
6163
}
6264

6365
/** @inheritDoc */
6466
public function has_child_node( ?string $rule_name = null ): bool {
65-
$this->materialize_native_children();
66-
return parent::has_child_node( $rule_name );
67+
if ( $this->was_mutated() ) {
68+
return parent::has_child_node( $rule_name );
69+
}
70+
return wp_sqlite_mysql_native_ast_has_child_node( $this->native_ast, $this->native_node_index, $rule_name );
6771
}
6872

6973
/** @inheritDoc */
7074
public function has_child_token( ?int $token_id = null ): bool {
71-
$this->materialize_native_children();
72-
return parent::has_child_token( $token_id );
75+
if ( $this->was_mutated() ) {
76+
return parent::has_child_token( $token_id );
77+
}
78+
return wp_sqlite_mysql_native_ast_has_child_token( $this->native_ast, $this->native_node_index, $token_id );
7379
}
7480

7581
/** @inheritDoc */
7682
public function get_first_child() {
77-
$this->materialize_native_children();
78-
return parent::get_first_child();
83+
if ( $this->was_mutated() ) {
84+
return parent::get_first_child();
85+
}
86+
return wp_sqlite_mysql_native_ast_get_first_child( $this->native_ast, $this->native_node_index );
7987
}
8088

8189
/** @inheritDoc */
8290
public function get_first_child_node( ?string $rule_name = null ): ?WP_Parser_Node {
83-
$this->materialize_native_children();
84-
return parent::get_first_child_node( $rule_name );
91+
if ( $this->was_mutated() ) {
92+
return parent::get_first_child_node( $rule_name );
93+
}
94+
return wp_sqlite_mysql_native_ast_get_first_child_node( $this->native_ast, $this->native_node_index, $rule_name );
8595
}
8696

8797
/** @inheritDoc */
8898
public function get_first_child_token( ?int $token_id = null ): ?WP_Parser_Token {
89-
$this->materialize_native_children();
90-
return parent::get_first_child_token( $token_id );
99+
if ( $this->was_mutated() ) {
100+
return parent::get_first_child_token( $token_id );
101+
}
102+
return wp_sqlite_mysql_native_ast_get_first_child_token( $this->native_ast, $this->native_node_index, $token_id );
91103
}
92104

93105
/** @inheritDoc */
94106
public function get_first_descendant_node( ?string $rule_name = null ): ?WP_Parser_Node {
95-
$this->materialize_native_children();
96-
return parent::get_first_descendant_node( $rule_name );
107+
if ( $this->was_mutated() ) {
108+
return parent::get_first_descendant_node( $rule_name );
109+
}
110+
return wp_sqlite_mysql_native_ast_get_first_descendant_node( $this->native_ast, $this->native_node_index, $rule_name );
97111
}
98112

99113
/** @inheritDoc */
100114
public function get_first_descendant_token( ?int $token_id = null ): ?WP_Parser_Token {
101-
$this->materialize_native_children();
102-
return parent::get_first_descendant_token( $token_id );
115+
if ( $this->was_mutated() ) {
116+
return parent::get_first_descendant_token( $token_id );
117+
}
118+
return wp_sqlite_mysql_native_ast_get_first_descendant_token( $this->native_ast, $this->native_node_index, $token_id );
103119
}
104120

105121
/** @inheritDoc */
106122
public function get_children(): array {
107-
$this->materialize_native_children();
108-
return parent::get_children();
123+
if ( $this->was_mutated() ) {
124+
return parent::get_children();
125+
}
126+
return wp_sqlite_mysql_native_ast_get_children( $this->native_ast, $this->native_node_index );
109127
}
110128

111129
/** @inheritDoc */
112130
public function get_child_nodes( ?string $rule_name = null ): array {
113-
$this->materialize_native_children();
114-
return parent::get_child_nodes( $rule_name );
131+
if ( $this->was_mutated() ) {
132+
return parent::get_child_nodes( $rule_name );
133+
}
134+
return wp_sqlite_mysql_native_ast_get_child_nodes( $this->native_ast, $this->native_node_index, $rule_name );
115135
}
116136

117137
/** @inheritDoc */
118138
public function get_child_tokens( ?int $token_id = null ): array {
119-
$this->materialize_native_children();
120-
return parent::get_child_tokens( $token_id );
139+
if ( $this->was_mutated() ) {
140+
return parent::get_child_tokens( $token_id );
141+
}
142+
return wp_sqlite_mysql_native_ast_get_child_tokens( $this->native_ast, $this->native_node_index, $token_id );
121143
}
122144

123145
/** @inheritDoc */
124146
public function get_descendants(): array {
125-
$this->materialize_native_children();
126-
return parent::get_descendants();
147+
if ( $this->was_mutated() ) {
148+
return parent::get_descendants();
149+
}
150+
return wp_sqlite_mysql_native_ast_get_descendants( $this->native_ast, $this->native_node_index );
127151
}
128152

129153
/** @inheritDoc */
130154
public function get_descendant_nodes( ?string $rule_name = null ): array {
131-
$this->materialize_native_children();
132-
return parent::get_descendant_nodes( $rule_name );
155+
if ( $this->was_mutated() ) {
156+
return parent::get_descendant_nodes( $rule_name );
157+
}
158+
return wp_sqlite_mysql_native_ast_get_descendant_nodes( $this->native_ast, $this->native_node_index, $rule_name );
133159
}
134160

135161
/** @inheritDoc */
136162
public function get_descendant_tokens( ?int $token_id = null ): array {
137-
$this->materialize_native_children();
138-
return parent::get_descendant_tokens( $token_id );
163+
if ( $this->was_mutated() ) {
164+
return parent::get_descendant_tokens( $token_id );
165+
}
166+
return wp_sqlite_mysql_native_ast_get_descendant_tokens( $this->native_ast, $this->native_node_index, $token_id );
139167
}
140168

141169
/** @inheritDoc */
142170
public function get_start(): int {
143-
$this->materialize_native_children();
144-
return parent::get_start();
171+
if ( $this->was_mutated() ) {
172+
return parent::get_start();
173+
}
174+
return wp_sqlite_mysql_native_ast_get_start( $this->native_ast, $this->native_node_index );
145175
}
146176

147177
/** @inheritDoc */
148178
public function get_length(): int {
149-
$this->materialize_native_children();
150-
return parent::get_length();
179+
if ( $this->was_mutated() ) {
180+
return parent::get_length();
181+
}
182+
return wp_sqlite_mysql_native_ast_get_length( $this->native_ast, $this->native_node_index );
151183
}
152184

153185
/**

0 commit comments

Comments
 (0)