1use std::sync::{Arc, LazyLock};
5
6use reifydb_core::{internal_error, value::column::columns::Columns};
7use reifydb_routine::routine::registry::Routines;
8use reifydb_rql::instruction::{Instruction, ScopeType};
9use reifydb_runtime::context::RuntimeContext;
10use reifydb_transaction::transaction::Transaction;
11use reifydb_value::{
12 params::Params,
13 util::bitvec::BitVec,
14 value::{Value, frame::frame::Frame, identity::IdentityId},
15};
16
17use super::{
18 exec::{
19 mask::{LoopMaskState, MaskFrame, extract_bool_bitvec},
20 stack::strip_dollar_prefix,
21 },
22 instruction::{
23 ddl::{
24 alter::{
25 identity::alter_identity, remote_namespace::alter_remote_namespace,
26 sequence::alter_table_sequence, table::execute_alter_table,
27 },
28 create::{
29 binding::create_binding, deferred::create_deferred_view, dictionary::create_dictionary,
30 migration::create_migration, namespace::create_namespace,
31 primary_key::create_primary_key, procedure::create_procedure,
32 property::create_column_property, remote_namespace::create_remote_namespace,
33 ringbuffer::create_ringbuffer, series::create_series, sink::create_sink,
34 source::create_source, subscription::create_subscription, sumtype::create_sumtype,
35 table::create_table, tag::create_tag, test::create_test,
36 transactional::create_transactional_view,
37 },
38 drop::{
39 binding::drop_binding, dictionary::drop_dictionary, namespace::drop_namespace,
40 procedure::drop_procedure, ringbuffer::drop_ringbuffer, series::drop_series,
41 sink::drop_sink, source::drop_source, subscription::drop_subscription,
42 sumtype::drop_sumtype, table::drop_table, view::drop_view,
43 },
44 },
45 dml::{
46 dictionary_insert::insert_dictionary, ringbuffer_delete::delete_ringbuffer,
47 ringbuffer_insert::insert_ringbuffer, ringbuffer_update::update_ringbuffer,
48 series_delete::delete_series, series_insert::insert_series, series_update::update_series,
49 table_delete::delete, table_insert::insert_table, table_update::update_table,
50 },
51 },
52 services::Services,
53 stack::{ControlFlow, Stack, SymbolTable, Variable},
54};
55use crate::{
56 Result,
57 expression::context::EvalContext,
58 vm::instruction::ddl::{
59 alter::policy::alter_policy,
60 create::{
61 authentication::create_authentication, event::create_event, identity::create_identity,
62 identity_attribute::create_identity_attribute, policy::create_policy, role::create_role,
63 },
64 drop::{
65 authentication::drop_authentication, handler::drop_handler, identity::drop_identity,
66 identity_attribute::drop_identity_attribute, policy::drop_policy, role::drop_role,
67 test::drop_test,
68 },
69 grant::grant,
70 revoke::revoke,
71 },
72};
73
74pub static EMPTY_PARAMS: LazyLock<Params> = LazyLock::new(|| Params::None);
75
76pub struct Vm<'a> {
77 pub(crate) ip: usize,
78 pub(crate) iteration_count: usize,
79 pub(crate) stack: Stack,
80 pub symbols: SymbolTable,
81 pub control_flow: ControlFlow,
82 pub(crate) dispatch_depth: u8,
83
84 pub(crate) batch_size: usize,
85
86 pub(crate) active_mask: Option<BitVec>,
87
88 pub(crate) mask_stack: Vec<MaskFrame>,
89
90 pub(crate) loop_mask_stack: Vec<LoopMaskState>,
91
92 pub(crate) params: &'a Params,
93 pub(crate) routines: &'a Routines,
94 pub(crate) runtime_context: &'a RuntimeContext,
95 pub(crate) identity: IdentityId,
96}
97
98impl<'a> Vm<'a> {
99 pub fn from_services(
100 symbols: SymbolTable,
101 services: &'a Services,
102 params: &'a Params,
103 identity: IdentityId,
104 ) -> Self {
105 Self::build(symbols, 1, params, &services.routines, &services.runtime_context, identity)
106 }
107
108 pub fn with_batch_size_from_services(
109 symbols: SymbolTable,
110 batch_size: usize,
111 services: &'a Services,
112 params: &'a Params,
113 identity: IdentityId,
114 ) -> Self {
115 Self::build(symbols, batch_size, params, &services.routines, &services.runtime_context, identity)
116 }
117
118 fn build(
119 symbols: SymbolTable,
120 batch_size: usize,
121 params: &'a Params,
122 routines: &'a Routines,
123 runtime_context: &'a RuntimeContext,
124 identity: IdentityId,
125 ) -> Self {
126 Self {
127 ip: 0,
128 iteration_count: 0,
129 stack: Stack::new(),
130 symbols,
131 control_flow: ControlFlow::Normal,
132 dispatch_depth: 0,
133 batch_size,
134 active_mask: None,
135 mask_stack: Vec::new(),
136 loop_mask_stack: Vec::new(),
137 params,
138 routines,
139 runtime_context,
140 identity,
141 }
142 }
143
144 pub(crate) fn eval_ctx(&self) -> EvalContext<'_> {
145 EvalContext {
146 params: self.params,
147 symbols: &self.symbols,
148 routines: self.routines,
149 runtime_context: self.runtime_context,
150 arena: None,
151 identity: self.identity,
152 is_aggregate_context: false,
153 columns: Columns::empty(),
154 row_count: self.batch_size,
155 target: None,
156 take: None,
157 }
158 }
159
160 pub(crate) fn run_isolated_body(
161 &mut self,
162 services: &Arc<Services>,
163 tx: &mut Transaction<'_>,
164 instructions: &[Instruction],
165 result: &mut Vec<Frame>,
166 ) -> Result<()> {
167 let saved = self.params;
168 self.params = &EMPTY_PARAMS;
169 let run_result = self.run(services, tx, instructions, result);
170 self.params = saved;
171 run_result
172 }
173
174 pub(crate) fn pop_value(&mut self) -> Result<Value> {
175 match self.stack.pop()? {
176 Variable::Columns {
177 columns: c,
178 } if c.is_scalar() => Ok(c.scalar_value()),
179 _ => Err(internal_error!("Expected scalar value on stack")),
180 }
181 }
182
183 pub(crate) fn pop_as_columns(&mut self) -> Result<Columns> {
184 match self.stack.pop()? {
185 Variable::Columns {
186 columns: c,
187 ..
188 }
189 | Variable::ForIterator {
190 columns: c,
191 ..
192 } => Ok(c),
193 Variable::Closure(_) => Ok(Columns::single_row([("value", Value::none())])),
194 }
195 }
196
197 pub(crate) fn run(
198 &mut self,
199 services: &Arc<Services>,
200 tx: &mut Transaction<'_>,
201 instructions: &[Instruction],
202 result: &mut Vec<Frame>,
203 ) -> Result<()> {
204 let params = self.params;
205 while self.ip < instructions.len() {
206 let _ = self.batch_size > 1 && self.check_mask_merge_point()?;
207
208 match &instructions[self.ip] {
209 Instruction::Halt => return Ok(()),
210 Instruction::Nop => {}
211
212 Instruction::PushConst(v) => self.exec_push_const(v),
213 Instruction::PushNone => self.exec_push_none(),
214 Instruction::Pop => self.exec_pop()?,
215 Instruction::Dup => self.exec_dup()?,
216
217 Instruction::LoadVar(f) => self.exec_load_var(f)?,
218 Instruction::StoreVar(f) => {
219 if self.batch_size > 1 && self.is_masked() {
220 let name = strip_dollar_prefix(f.text());
221 let value = self.stack.pop()?;
222 self.exec_store_var_masked(name, value)?;
223 } else if self.batch_size > 1 {
224 let name = strip_dollar_prefix(f.text());
225 let value = self.stack.pop()?;
226 self.symbols.reassign(name.to_string(), value)?;
227 } else {
228 self.exec_store_var(f)?;
229 }
230 }
231 Instruction::DeclareVar(f) => self.exec_declare_var(f)?,
232 Instruction::FieldAccess {
233 object,
234 field,
235 } => self.exec_field_access(object, field)?,
236
237 Instruction::Add => self.exec_add()?,
238 Instruction::Sub => self.exec_sub()?,
239 Instruction::Mul => self.exec_mul()?,
240 Instruction::Div => self.exec_div()?,
241 Instruction::Rem => self.exec_rem()?,
242 Instruction::Negate => self.exec_negate()?,
243 Instruction::LogicNot => self.exec_logic_not()?,
244
245 Instruction::CmpEq => self.exec_cmp_eq()?,
246 Instruction::CmpNe => self.exec_cmp_ne()?,
247 Instruction::CmpLt => self.exec_cmp_lt()?,
248 Instruction::CmpLe => self.exec_cmp_le()?,
249 Instruction::CmpGt => self.exec_cmp_gt()?,
250 Instruction::CmpGe => self.exec_cmp_ge()?,
251
252 Instruction::LogicAnd => self.exec_logic_and()?,
253 Instruction::LogicOr => self.exec_logic_or()?,
254 Instruction::LogicXor => self.exec_logic_xor()?,
255 Instruction::Between => self.exec_between()?,
256 Instruction::InList {
257 count,
258 negated,
259 } => self.exec_in_list(*count, *negated)?,
260 Instruction::Cast(target) => self.exec_cast(target)?,
261
262 Instruction::Jump(addr) => {
263 if self.batch_size > 1
264 && (!self.mask_stack.is_empty() || !self.loop_mask_stack.is_empty())
265 {
266 if self.exec_jump_masked(*addr)? {
267 continue;
268 }
269 } else {
270 self.exec_jump(*addr)?;
271 continue;
272 }
273 }
274 Instruction::JumpIfFalsePop(addr) => {
275 if self.batch_size > 1 {
276 let is_while_loop = instructions.get(self.ip + 1).is_some_and(|next| {
277 matches!(next, Instruction::EnterScope(ScopeType::Loop))
278 });
279
280 if is_while_loop
281 && self.loop_mask_stack
282 .last()
283 .is_none_or(|s| s.loop_end_addr != *addr)
284 {
285 let var = self.stack.pop()?;
286 let bool_bv = extract_bool_bitvec(&var)?;
287 let parent = self.effective_mask();
288 let candidate = self.intersect_condition(&bool_bv);
289
290 if candidate == parent {
291 } else if candidate.none() {
292 self.ip = *addr;
293 continue;
294 } else {
295 self.enter_loop_mask(*addr, candidate);
296 }
297 } else if self.exec_jump_if_false_pop_columnar(*addr)? {
298 continue;
299 }
300 } else if self.exec_jump_if_false_pop(*addr)? {
301 continue;
302 }
303 }
304 Instruction::JumpIfTruePop(addr) => {
305 if self.batch_size > 1 {
306 if self.exec_jump_if_true_pop_columnar(*addr)? {
307 continue;
308 }
309 } else if self.exec_jump_if_true_pop(*addr)? {
310 continue;
311 }
312 }
313 Instruction::EnterScope(scope_type) => self.exec_enter_scope(scope_type),
314 Instruction::ExitScope => self.exec_exit_scope()?,
315 Instruction::Break {
316 exit_scopes,
317 addr,
318 } => {
319 if self.batch_size > 1 && !self.loop_mask_stack.is_empty() {
320 self.exec_break_masked(*exit_scopes, *addr)?;
321 } else {
322 self.exec_break(*exit_scopes, *addr)?;
323 }
324 continue;
325 }
326 Instruction::Continue {
327 exit_scopes,
328 addr,
329 } => {
330 if self.batch_size > 1 && !self.loop_mask_stack.is_empty() {
331 self.exec_continue_masked(*exit_scopes, *addr)?;
332 } else {
333 self.exec_continue(*exit_scopes, *addr)?;
334 }
335 continue;
336 }
337
338 Instruction::ForInit {
339 variable_name,
340 } => self.exec_for_init(variable_name)?,
341 Instruction::ForNext {
342 variable_name,
343 addr,
344 } => {
345 if self.exec_for_next(variable_name, *addr)? {
346 continue;
347 }
348 }
349
350 Instruction::DefineFunction(node) => self.exec_define_function(node),
351 Instruction::Call {
352 name,
353 arity,
354 is_procedure_call,
355 } => {
356 self.exec_call(services, tx, name, *arity, *is_procedure_call)?;
357 }
358 Instruction::ReturnValue => {
359 self.exec_return_value()?;
360 return Ok(());
361 }
362 Instruction::ReturnVoid => {
363 self.exec_return_void();
364 return Ok(());
365 }
366 Instruction::DefineClosure(def) => self.exec_define_closure(def),
367
368 Instruction::Emit => self.exec_emit(result),
369 Instruction::Append {
370 target,
371 } => self.exec_append(target)?,
372
373 Instruction::Query(plan) => self.exec_query(services, tx, plan, params)?,
374
375 Instruction::CreateNamespace(n) => {
376 self.exec_ddl(services, tx, |s, t| create_namespace(s, t, n.clone()))?
377 }
378 Instruction::CreateRemoteNamespace(n) => {
379 self.exec_ddl(services, tx, |s, t| create_remote_namespace(s, t, n.clone()))?
380 }
381 Instruction::CreateTable(n) => {
382 self.exec_ddl(services, tx, |s, t| create_table(s, t, n.clone()))?
383 }
384 Instruction::CreateRingBuffer(n) => {
385 self.exec_ddl(services, tx, |s, t| create_ringbuffer(s, t, n.clone()))?
386 }
387 Instruction::CreateDeferredView(n) => {
388 self.exec_ddl(services, tx, |s, t| create_deferred_view(s, t, n.clone()))?
389 }
390 Instruction::CreateTransactionalView(n) => {
391 self.exec_ddl(services, tx, |s, t| create_transactional_view(s, t, n.clone()))?
392 }
393 Instruction::CreateDictionary(n) => {
394 self.exec_ddl(services, tx, |s, t| create_dictionary(s, t, n.clone()))?
395 }
396 Instruction::CreateSumType(n) => {
397 self.exec_ddl(services, tx, |s, t| create_sumtype(s, t, n.clone()))?
398 }
399 Instruction::CreatePrimaryKey(n) => {
400 self.exec_ddl(services, tx, |s, t| create_primary_key(s, t, n.clone()))?
401 }
402 Instruction::CreateColumnProperty(n) => {
403 self.exec_ddl(services, tx, |s, t| create_column_property(s, t, n.clone()))?
404 }
405 Instruction::CreateProcedure(n) => {
406 self.exec_ddl(services, tx, |s, t| create_procedure(s, t, n.clone()))?
407 }
408 Instruction::CreateSeries(n) => {
409 self.exec_ddl(services, tx, |s, t| create_series(s, t, n.clone()))?
410 }
411 Instruction::CreateEvent(n) => {
412 self.exec_ddl(services, tx, |s, t| create_event(s, t, n.clone()))?
413 }
414 Instruction::CreateTag(n) => {
415 self.exec_ddl(services, tx, |s, t| create_tag(s, t, n.clone()))?
416 }
417 Instruction::CreateSource(n) => {
418 self.exec_ddl(services, tx, |s, t| create_source(s, t, n.clone()))?
419 }
420 Instruction::CreateSink(n) => {
421 self.exec_ddl(services, tx, |s, t| create_sink(s, t, n.clone()))?
422 }
423 Instruction::CreateBinding(n) => {
424 self.exec_ddl(services, tx, |s, t| create_binding(s, t, n.clone()))?
425 }
426 Instruction::CreateTest(n) => {
427 self.exec_ddl(services, tx, |s, t| create_test(s, t, n.clone()))?
428 }
429 Instruction::CreateMigration(n) => {
430 self.exec_ddl(services, tx, |s, t| create_migration(s, t, n.clone()))?
431 }
432 Instruction::CreateIdentity(n) => {
433 let params = self.params;
434 self.exec_ddl(services, tx, |s, t| create_identity(s, t, n.clone(), params))?
435 }
436 Instruction::CreateIdentityAttribute(n) => {
437 self.exec_ddl(services, tx, |s, t| create_identity_attribute(s, t, n.clone()))?
438 }
439 Instruction::CreateRole(n) => {
440 self.exec_ddl(services, tx, |s, t| create_role(s, t, n.clone()))?
441 }
442 Instruction::CreatePolicy(n) => {
443 self.exec_ddl(services, tx, |s, t| create_policy(s, t, n.clone()))?
444 }
445 Instruction::CreateAuthentication(n) => {
446 self.exec_ddl(services, tx, |s, t| create_authentication(s, t, n.clone()))?
447 }
448 Instruction::Grant(n) => self.exec_ddl(services, tx, |s, t| grant(s, t, n.clone()))?,
449 Instruction::Revoke(n) => {
450 self.exec_ddl(services, tx, |s, t| revoke(s, t, n.clone()))?
451 }
452
453 Instruction::CreateSubscription(n) => {
454 self.exec_ddl_sub(services, tx, |s, t| create_subscription(s, t, n.clone()))?
455 }
456
457 Instruction::AlterTable(n) => {
458 self.exec_ddl(services, tx, |s, t| execute_alter_table(s, t, n.clone()))?
459 }
460 Instruction::AlterRemoteNamespace(n) => {
461 self.exec_ddl(services, tx, |s, t| alter_remote_namespace(s, t, n.clone()))?
462 }
463 Instruction::AlterSequence(n) => {
464 self.exec_ddl(services, tx, |s, t| alter_table_sequence(s, t, n.clone()))?
465 }
466 Instruction::AlterIdentity(n) => {
467 let params = self.params;
468 self.exec_ddl(services, tx, |s, t| alter_identity(s, t, n.clone(), params))?
469 }
470 Instruction::AlterPolicy(n) => {
471 self.exec_ddl(services, tx, |s, t| alter_policy(s, t, n.clone()))?
472 }
473
474 Instruction::DropNamespace(n) => {
475 self.exec_ddl(services, tx, |s, t| drop_namespace(s, t, n.clone()))?
476 }
477 Instruction::DropTable(n) => {
478 self.exec_ddl(services, tx, |s, t| drop_table(s, t, n.clone()))?
479 }
480 Instruction::DropView(n) => {
481 self.exec_ddl(services, tx, |s, t| drop_view(s, t, n.clone()))?
482 }
483 Instruction::DropRingBuffer(n) => {
484 self.exec_ddl(services, tx, |s, t| drop_ringbuffer(s, t, n.clone()))?
485 }
486 Instruction::DropSeries(n) => {
487 self.exec_ddl(services, tx, |s, t| drop_series(s, t, n.clone()))?
488 }
489 Instruction::DropDictionary(n) => {
490 self.exec_ddl(services, tx, |s, t| drop_dictionary(s, t, n.clone()))?
491 }
492 Instruction::DropSumType(n) => {
493 self.exec_ddl(services, tx, |s, t| drop_sumtype(s, t, n.clone()))?
494 }
495 Instruction::DropSource(n) => {
496 self.exec_ddl(services, tx, |s, t| drop_source(s, t, n.clone()))?
497 }
498 Instruction::DropSink(n) => {
499 self.exec_ddl(services, tx, |s, t| drop_sink(s, t, n.clone()))?
500 }
501 Instruction::DropProcedure(n) => {
502 self.exec_ddl(services, tx, |s, t| drop_procedure(s, t, n.clone()))?
503 }
504 Instruction::DropHandler(n) => {
505 self.exec_ddl(services, tx, |s, t| drop_handler(s, t, n.clone()))?
506 }
507 Instruction::DropTest(n) => {
508 self.exec_ddl(services, tx, |s, t| drop_test(s, t, n.clone()))?
509 }
510 Instruction::DropBinding(n) => {
511 self.exec_ddl(services, tx, |s, t| drop_binding(s, t, n.clone()))?
512 }
513 Instruction::DropIdentity(n) => {
514 self.exec_ddl(services, tx, |s, t| drop_identity(s, t, n.clone()))?
515 }
516 Instruction::DropIdentityAttribute(n) => {
517 self.exec_ddl(services, tx, |s, t| drop_identity_attribute(s, t, n.clone()))?
518 }
519 Instruction::DropRole(n) => {
520 self.exec_ddl(services, tx, |s, t| drop_role(s, t, n.clone()))?
521 }
522 Instruction::DropPolicy(n) => {
523 self.exec_ddl(services, tx, |s, t| drop_policy(s, t, n.clone()))?
524 }
525 Instruction::DropAuthentication(n) => {
526 self.exec_ddl(services, tx, |s, t| drop_authentication(s, t, n.clone()))?
527 }
528
529 Instruction::DropSubscription(n) => {
530 self.exec_ddl_sub(services, tx, |s, t| drop_subscription(s, t, n.clone()))?
531 }
532
533 Instruction::Delete(n) => {
534 self.exec_dml_with_params(services, tx, params, |s, t, p, sym| {
535 delete(s, t, n.clone(), p, sym)
536 })?
537 }
538 Instruction::DeleteRingBuffer(n) => {
539 self.exec_dml_with_params(services, tx, params, |s, t, p, sym| {
540 delete_ringbuffer(s, t, n.clone(), p, sym)
541 })?
542 }
543 Instruction::DeleteSeries(n) => {
544 self.exec_dml_with_params(services, tx, params, |s, t, p, sym| {
545 delete_series(s, t, n.clone(), p, sym)
546 })?
547 }
548 Instruction::Update(n) => {
549 self.exec_dml_with_params(services, tx, params, |s, t, p, sym| {
550 update_table(s, t, n.clone(), p, sym)
551 })?
552 }
553 Instruction::UpdateRingBuffer(n) => {
554 self.exec_dml_with_params(services, tx, params, |s, t, p, sym| {
555 update_ringbuffer(s, t, n.clone(), p, sym)
556 })?
557 }
558 Instruction::UpdateSeries(n) => {
559 self.exec_dml_with_params(services, tx, params, |s, t, p, sym| {
560 update_series(s, t, n.clone(), p, sym)
561 })?
562 }
563 Instruction::InsertTable(n) => {
564 self.exec_dml_with_mut_symbols(services, tx, |s, t, sym| {
565 insert_table(s, t, n.clone(), sym)
566 })?
567 }
568 Instruction::InsertDictionary(n) => {
569 self.exec_dml_with_mut_symbols(services, tx, |s, t, sym| {
570 insert_dictionary(s, t, n.clone(), sym)
571 })?
572 }
573 Instruction::InsertRingBuffer(n) => {
574 self.exec_dml_with_params(services, tx, params, |s, t, p, sym| {
575 insert_ringbuffer(s, t, n.clone(), p, sym)
576 })?
577 }
578 Instruction::InsertSeries(n) => {
579 self.exec_dml_with_params(services, tx, params, |s, t, p, sym| {
580 insert_series(s, t, n.clone(), p, sym)
581 })?
582 }
583
584 Instruction::Dispatch(n) => self.exec_dispatch(services, tx, n, params)?,
585 Instruction::Migrate(n) => self.exec_migrate(services, tx, n)?,
586 Instruction::RollbackMigration(n) => self.exec_rollback_migration(services, tx, n)?,
587 Instruction::AssertBlock(n) => self.exec_assert_block(services, tx, n)?,
588 }
589
590 self.ip += 1;
591
592 if !self.control_flow.is_normal() {
593 return Ok(());
594 }
595 }
596 Ok(())
597 }
598}