From 4384659e5fc9f20646abda58891d1f99f3dbd89f Mon Sep 17 00:00:00 2001 From: PThorpe92 Date: Mon, 24 Mar 2025 20:44:29 -0400 Subject: [PATCH 1/2] Adjust vtab schema creation to display the underlying columns --- core/translate/mod.rs | 2 +- core/translate/schema.rs | 41 +++++++++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/core/translate/mod.rs b/core/translate/mod.rs index 739ae5f03..f2007825d 100644 --- a/core/translate/mod.rs +++ b/core/translate/mod.rs @@ -78,7 +78,7 @@ pub fn translate( ast::Stmt::CreateTrigger { .. } => bail_parse_error!("CREATE TRIGGER not supported yet"), ast::Stmt::CreateView { .. } => bail_parse_error!("CREATE VIEW not supported yet"), ast::Stmt::CreateVirtualTable(vtab) => { - translate_create_virtual_table(*vtab, schema, query_mode)? + translate_create_virtual_table(*vtab, schema, query_mode, &syms)? } ast::Stmt::Delete(delete) => { let Delete { diff --git a/core/translate/schema.rs b/core/translate/schema.rs index a887bdef8..43fdd6017 100644 --- a/core/translate/schema.rs +++ b/core/translate/schema.rs @@ -1,6 +1,8 @@ use std::fmt::Display; +use std::rc::Rc; use crate::ast; +use crate::ext::VTabImpl; use crate::schema::Schema; use crate::translate::ProgramBuilder; use crate::translate::ProgramBuilderOpts; @@ -9,8 +11,10 @@ use crate::util::PRIMARY_KEY_AUTOMATIC_INDEX_NAME_PREFIX; use crate::vdbe::builder::CursorType; use crate::vdbe::insn::{CmpInsFlags, Insn}; use crate::LimboError; +use crate::SymbolTable; use crate::{bail_parse_error, Result}; +use limbo_ext::VTabKind; use limbo_sqlite3_parser::ast::{fmt::ToTokens, CreateVirtualTable}; pub fn translate_create_table( @@ -398,7 +402,7 @@ fn create_table_body_to_str(tbl_name: &ast::QualifiedName, body: &ast::CreateTab sql } -fn create_vtable_body_to_str(vtab: &CreateVirtualTable) -> String { +fn create_vtable_body_to_str(vtab: &CreateVirtualTable, module: Rc) -> String { let args = if let Some(args) = &vtab.args { args.iter() .map(|arg| arg.to_string()) @@ -412,8 +416,25 @@ fn create_vtable_body_to_str(vtab: &CreateVirtualTable) -> String { } else { "" }; + let ext_args = vtab + .args + .as_ref() + .unwrap_or(&vec![]) + .iter() + .map(|a| limbo_ext::Value::from_text(a.to_string())) + .collect::>(); + let schema = module + .implementation + .init_schema(ext_args) + .unwrap_or_default(); + let vtab_args = if let Some(first_paren) = schema.find('(') { + let closing_paren = schema.rfind(')').unwrap_or_default(); + &schema[first_paren..=closing_paren] + } else { + "()" + }; format!( - "CREATE VIRTUAL TABLE {} {} USING {}{}", + "CREATE VIRTUAL TABLE {} {} USING {}{}\n /*{}{}*/;", vtab.tbl_name.name.0, if_not_exists, vtab.module_name.0, @@ -421,7 +442,9 @@ fn create_vtable_body_to_str(vtab: &CreateVirtualTable) -> String { String::new() } else { format!("({})", args) - } + }, + vtab.tbl_name.name.0, + vtab_args ) } @@ -429,6 +452,7 @@ pub fn translate_create_virtual_table( vtab: CreateVirtualTable, schema: &Schema, query_mode: QueryMode, + syms: &SymbolTable, ) -> Result { let ast::CreateVirtualTable { if_not_exists, @@ -440,7 +464,12 @@ pub fn translate_create_virtual_table( let table_name = tbl_name.name.0.clone(); let module_name_str = module_name.0.clone(); let args_vec = args.clone().unwrap_or_default(); - + let Some(vtab_module) = syms.vtab_modules.get(&module_name_str) else { + bail_parse_error!("no such module: {}", module_name_str); + }; + if !vtab_module.module_kind.eq(&VTabKind::VirtualTable) { + bail_parse_error!("module {} is not a virtual table", module_name_str); + }; if schema.get_table(&table_name).is_some() && *if_not_exists { let mut program = ProgramBuilder::new(ProgramBuilderOpts { query_mode, @@ -465,7 +494,6 @@ pub fn translate_create_virtual_table( let module_name_reg = program.emit_string8_new_reg(module_name_str.clone()); let table_name_reg = program.emit_string8_new_reg(table_name.clone()); - let args_reg = if !args_vec.is_empty() { let args_start = program.alloc_register(); @@ -491,7 +519,6 @@ pub fn translate_create_virtual_table( table_name: table_name_reg, args_reg, }); - let table = schema.get_btree_table(SQLITE_TABLEID).unwrap(); let sqlite_schema_cursor_id = program.alloc_cursor_id( Some(SQLITE_TABLEID.to_owned()), @@ -503,7 +530,7 @@ pub fn translate_create_virtual_table( }); program.emit_insn(Insn::OpenWriteAwait {}); - let sql = create_vtable_body_to_str(&vtab); + let sql = create_vtable_body_to_str(&vtab, vtab_module.clone()); emit_schema_entry( &mut program, sqlite_schema_cursor_id, From 334f0a928ac24f3577b5266e7dc384bc5895613a Mon Sep 17 00:00:00 2001 From: PThorpe92 Date: Mon, 24 Mar 2025 21:05:50 -0400 Subject: [PATCH 2/2] Adjust test to reflect new parse error --- core/translate/schema.rs | 2 +- testing/cli_tests/extensions.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/translate/schema.rs b/core/translate/schema.rs index 43fdd6017..8a5accea2 100644 --- a/core/translate/schema.rs +++ b/core/translate/schema.rs @@ -434,7 +434,7 @@ fn create_vtable_body_to_str(vtab: &CreateVirtualTable, module: Rc) -> "()" }; format!( - "CREATE VIRTUAL TABLE {} {} USING {}{}\n /*{}{}*/;", + "CREATE VIRTUAL TABLE {} {} USING {}{}\n /*{}{}*/", vtab.tbl_name.name.0, if_not_exists, vtab.module_name.0, diff --git a/testing/cli_tests/extensions.py b/testing/cli_tests/extensions.py index 56784b286..92d058ff8 100755 --- a/testing/cli_tests/extensions.py +++ b/testing/cli_tests/extensions.py @@ -341,7 +341,7 @@ def test_kv(): limbo = TestLimboShell() limbo.run_test_fn( "create virtual table t using kv_store;", - lambda res: "Virtual table module not found: kv_store" in res, + lambda res: "Parse error: no such module: kv_store" in res, ) limbo.execute_dot(f".load {ext_path}") limbo.run_test_fn(